def addbackup(self, file, hardlink=True, vfs=None): """Adds a backup of the file to the transaction Calling addbackup() creates a hardlink backup of the specified file that is used to recover the file in the event of the transaction aborting. * `file`: the file path, relative to .hg/store * `hardlink`: use a hardlink to quickly create the backup """ if file in self.map or file in self.backupmap: return backupfile = "%s.backup.%s" % (self.journal, file) if vfs is None: vfs = self.opener if vfs.exists(file): filepath = vfs.join(file) backuppath = self.opener.join(backupfile) util.copyfiles(filepath, backuppath, hardlink=hardlink) else: self.add(file, 0) return if self._queue: self._queue[-1][1].append((file, backupfile)) return self.backupentries.append((file, backupfile, None)) self.backupmap[file] = len(self.backupentries) - 1 self.backupsfile.write("%s\0%s\n" % (file, backupfile)) self.backupsfile.flush()
def addbackup(self, file, hardlink=True): """Adds a backup of the file to the transaction Calling addbackup() creates a hardlink backup of the specified file that is used to recover the file in the event of the transaction aborting. * `file`: the file path, relative to .hg/store * `hardlink`: use a hardlink to quickly create the backup """ if file in self.map or file in self.backupmap: return backupfile = "journal.%s" % file if self.opener.exists(file): filepath = self.opener.join(file) backuppath = self.opener.join(backupfile) util.copyfiles(filepath, backuppath, hardlink=hardlink) else: self.add(file, 0) return if self._queue: self._queue[-1][1].append((file, backupfile)) return self.backupentries.append((file, backupfile, None)) self.backupmap[file] = len(self.backupentries) - 1 self.backupsfile.write("%s\0%s\0" % (file, backupfile)) self.backupsfile.flush()
def copystore(ui, srcrepo, destpath): '''copy files from store of srcrepo in destpath returns destlock ''' destlock = None try: hardlink = None num = 0 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True) srcvfs = scmutil.vfs(srcrepo.sharedpath) dstvfs = scmutil.vfs(destpath) for f in srcrepo.store.copylist(): if srcpublishing and f.endswith('phaseroots'): continue dstbase = os.path.dirname(f) if dstbase and not dstvfs.exists(dstbase): dstvfs.mkdir(dstbase) if srcvfs.exists(f): if f.endswith('data'): # 'dstbase' may be empty (e.g. revlog format 0) lockfile = os.path.join(dstbase, "lock") # lock to avoid premature writing to the target destlock = lock.lock(dstvfs, lockfile) hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f), hardlink) num += n if hardlink: ui.debug("linked %d files\n" % num) else: ui.debug("copied %d files\n" % num) return destlock except: # re-raises release(destlock) raise
def copystore(ui, srcrepo, destpath): '''copy files from store of srcrepo in destpath returns destlock ''' destlock = None try: hardlink = None num = 0 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True) for f in srcrepo.store.copylist(): if srcpublishing and f.endswith('phaseroots'): continue src = os.path.join(srcrepo.sharedpath, f) dst = os.path.join(destpath, f) dstbase = os.path.dirname(dst) if dstbase and not os.path.exists(dstbase): os.mkdir(dstbase) if os.path.exists(src): if dst.endswith('data'): # lock to avoid premature writing to the target destlock = lock.lock(os.path.join(dstbase, "lock")) hardlink, n = util.copyfiles(src, dst, hardlink) num += n if hardlink: ui.debug("linked %d files\n" % num) else: ui.debug("copied %d files\n" % num) return destlock except: release(destlock) raise
def copystore(ui, srcrepo, destpath): """copy files from store of srcrepo in destpath returns destlock """ destlock = None try: hardlink = None num = 0 srcpublishing = srcrepo.ui.configbool("phases", "publish", True) srcvfs = scmutil.vfs(srcrepo.sharedpath) dstvfs = scmutil.vfs(destpath) for f in srcrepo.store.copylist(): if srcpublishing and f.endswith("phaseroots"): continue dstbase = os.path.dirname(f) if dstbase and not dstvfs.exists(dstbase): dstvfs.mkdir(dstbase) if srcvfs.exists(f): if f.endswith("data"): # 'dstbase' may be empty (e.g. revlog format 0) lockfile = os.path.join(dstbase, "lock") # lock to avoid premature writing to the target destlock = lock.lock(dstvfs, lockfile) hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f), hardlink) num += n if hardlink: ui.debug("linked %d files\n" % num) else: ui.debug("copied %d files\n" % num) return destlock except: # re-raises release(destlock) raise
def copystore(ui, srcrepo, destpath): """copy files from store of srcrepo in destpath returns destlock """ destlock = None try: hardlink = None num = 0 closetopic = [None] def prog(topic, pos): if pos is None: closetopic[0] = topic else: ui.progress(topic, pos + num) srcpublishing = srcrepo.publishing() srcvfs = scmutil.vfs(srcrepo.sharedpath) dstvfs = scmutil.vfs(destpath) for f in srcrepo.store.copylist(): if srcpublishing and f.endswith("phaseroots"): continue dstbase = os.path.dirname(f) if dstbase and not dstvfs.exists(dstbase): dstvfs.mkdir(dstbase) if srcvfs.exists(f): if f.endswith("data"): # 'dstbase' may be empty (e.g. revlog format 0) lockfile = os.path.join(dstbase, "lock") # lock to avoid premature writing to the target destlock = lock.lock(dstvfs, lockfile) hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f), hardlink, progress=prog) num += n if hardlink: ui.debug("linked %d files\n" % num) if closetopic[0]: ui.progress(closetopic[0], None) else: ui.debug("copied %d files\n" % num) if closetopic[0]: ui.progress(closetopic[0], None) return destlock except: # re-raises release(destlock) raise
def copystore(ui, srcrepo, destpath): '''copy files from store of srcrepo in destpath returns destlock ''' destlock = None try: hardlink = None num = 0 closetopic = [None] def prog(topic, pos): if pos is None: closetopic[0] = topic else: ui.progress(topic, pos + num) srcpublishing = srcrepo.publishing() srcvfs = scmutil.vfs(srcrepo.sharedpath) dstvfs = scmutil.vfs(destpath) for f in srcrepo.store.copylist(): if srcpublishing and f.endswith('phaseroots'): continue dstbase = os.path.dirname(f) if dstbase and not dstvfs.exists(dstbase): dstvfs.mkdir(dstbase) if srcvfs.exists(f): if f.endswith('data'): # 'dstbase' may be empty (e.g. revlog format 0) lockfile = os.path.join(dstbase, "lock") # lock to avoid premature writing to the target destlock = lock.lock(dstvfs, lockfile) hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f), hardlink, progress=prog) num += n if hardlink: ui.debug("linked %d files\n" % num) if closetopic[0]: ui.progress(closetopic[0], None) else: ui.debug("copied %d files\n" % num) if closetopic[0]: ui.progress(closetopic[0], None) return destlock except: # re-raises release(destlock) raise
def clone(ui, source, dest=None, pull=False, rev=None, update=True, stream=False): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository objects, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) """ if isinstance(source, str): origsource = ui.expandpath(source) source, rev, checkout = parseurl(origsource, rev) src_repo = repository(ui, source) else: src_repo = source origsource = source = src_repo.url() checkout = rev and rev[-1] or None if dest is None: dest = defaultdest(source) ui.status(_("destination directory: %s\n") % dest) dest = localpath(dest) source = localpath(source) if os.path.exists(dest): if not os.path.isdir(dest): raise util.Abort(_("destination '%s' already exists") % dest) elif os.listdir(dest): raise util.Abort(_("destination '%s' is not empty") % dest) class DirCleanup(object): def __init__(self, dir_): self.rmtree = shutil.rmtree self.dir_ = dir_ def close(self): self.dir_ = None def cleanup(self): if self.dir_: self.rmtree(self.dir_, True) src_lock = dest_lock = dir_cleanup = None try: if islocal(dest): dir_cleanup = DirCleanup(dest) abspath = origsource copy = False if src_repo.cancopy() and islocal(dest): abspath = os.path.abspath(util.drop_scheme('file', origsource)) copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail src_lock = src_repo.lock(wait=False) except error.LockError: copy = False if copy: src_repo.hook('preoutgoing', throw=True, source='clone') hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves dir_cleanup.dir_ = hgdir try: dest_path = hgdir os.mkdir(dest_path) except OSError, inst: if inst.errno == errno.EEXIST: dir_cleanup.close() raise util.Abort( _("destination '%s' already exists") % dest) raise for f in src_repo.store.copylist(): src = os.path.join(src_repo.path, f) dst = os.path.join(dest_path, f) dstbase = os.path.dirname(dst) if dstbase and not os.path.exists(dstbase): os.mkdir(dstbase) if os.path.exists(src): if dst.endswith('data'): # lock to avoid premature writing to the target dest_lock = lock.lock(os.path.join(dstbase, "lock")) util.copyfiles(src, dst) # we need to re-init the repo after manually copying the data # into it dest_repo = repository(ui, dest) src_repo.hook('outgoing', source='clone', node='0' * 40) else:
def clone(ui, source, dest=None, pull=False, rev=None, update=True, stream=False, branch=None): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The source and destination are URLs, as passed to the repository function. Returns a pair of repository objects, the source and newly created destination. The location of the source is added to the new repository's .hg/hgrc file, as the default to be used for future pulls and pushes. If an exception is raised, the partly cloned/updated destination repository will be deleted. Arguments: source: repository object or URL dest: URL of destination repository to create (defaults to base name of source repository) pull: always pull from source repository, even in local case stream: stream raw data uncompressed from repository (fast over LAN, slow over WAN) rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if destination is local repository (True means update to default rev, anything else is treated as a revision) branch: branches to clone """ if isinstance(source, str): origsource = ui.expandpath(source) source, branch = parseurl(origsource, branch) src_repo = repository(ui, source) else: src_repo = source origsource = source = src_repo.url() rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev) if dest is None: dest = defaultdest(source) ui.status(_("destination directory: %s\n") % dest) else: dest = ui.expandpath(dest) dest = localpath(dest) source = localpath(source) if os.path.exists(dest): if not os.path.isdir(dest): raise util.Abort(_("destination '%s' already exists") % dest) elif os.listdir(dest): raise util.Abort(_("destination '%s' is not empty") % dest) class DirCleanup(object): def __init__(self, dir_): self.rmtree = shutil.rmtree self.dir_ = dir_ def close(self): self.dir_ = None def cleanup(self): if self.dir_: self.rmtree(self.dir_, True) src_lock = dest_lock = dir_cleanup = None try: if islocal(dest): dir_cleanup = DirCleanup(dest) abspath = origsource copy = False if src_repo.cancopy() and islocal(dest): abspath = os.path.abspath(util.drop_scheme('file', origsource)) copy = not pull and not rev if copy: try: # we use a lock here because if we race with commit, we # can end up with extra data in the cloned revlogs that's # not pointed to by changesets, thus causing verify to # fail src_lock = src_repo.lock(wait=False) except error.LockError: copy = False if copy: src_repo.hook('preoutgoing', throw=True, source='clone') hgdir = os.path.realpath(os.path.join(dest, ".hg")) if not os.path.exists(dest): os.mkdir(dest) else: # only clean up directories we create ourselves dir_cleanup.dir_ = hgdir try: dest_path = hgdir os.mkdir(dest_path) except OSError, inst: if inst.errno == errno.EEXIST: dir_cleanup.close() raise util.Abort(_("destination '%s' already exists") % dest) raise for f in src_repo.store.copylist(): src = os.path.join(src_repo.sharedpath, f) dst = os.path.join(dest_path, f) dstbase = os.path.dirname(dst) if dstbase and not os.path.exists(dstbase): os.mkdir(dstbase) if os.path.exists(src): if dst.endswith('data'): # lock to avoid premature writing to the target dest_lock = lock.lock(os.path.join(dstbase, "lock")) util.copyfiles(src, dst) # we need to re-init the repo after manually copying the data # into it dest_repo = repository(ui, dest) src_repo.hook('outgoing', source='clone', node='0'*40) else:
def force_copy(src, dst): if not os.path.exists(src): # Tolerate empty source repository and optional files return util.copyfiles(src, dst)