def __init__(self, name, verbose=False): """Construct a Converter object.""" self.name = name self.verbose = verbose self.revisionmap = {} self.symlink_warned = {} self.prcs = PrcsProject(self.name) self.revisions = self.prcs.revisions() self.hgclient = hglib.open(".")
def __init__(self, name, verbose = False): """Construct a Converter object.""" self.name = name self.verbose = verbose self.revisionmap = {} self.symlink_warned = {} self.prcs = PrcsProject(self.name) self.revisions = self.prcs.revisions() self.hgclient = hglib.open(".")
def __init__(self, ui, path=None, rev=None): super(prcs_source, self).__init__(ui, path, rev) try: self._prcs = PrcsProject(path) self._revisions = self._prcs.revisions() except PrcsCommandError as error: ui.note(error.error_message) raise NoRepo() except PrcsError: raise NoRepo() self._cached_descriptor = {}
class Converter(object): def __init__(self, name, verbose = False): """Construct a Converter object.""" self.name = name self.verbose = verbose self.revisionmap = {} self.symlink_warned = {} self.prcs = PrcsProject(self.name) self.revisions = self.prcs.revisions() self.hgclient = hglib.open(".") def convert(self): """Convert all revisions in a project.""" list = sorted(self.revisions, key = lambda id: self.revisions[id]["date"]) for i in list: self.convertrevision(i) def convertrevision(self, version): version = str(version) if self.revisions[version].get("deleted"): sys.stderr.write("Ignored deleted version {0}\n".format(version)) return if self.verbose: sys.stderr.write("Converting version {0}\n".format(version)) descriptor = self.prcs.descriptor(version) parent = descriptor.parentversion() if parent is None: # It is a root revision. self.hgclient.update("null") parent_filemap = {} else: while self.revisions[str(parent)].get("deleted"): parent.minor -= 1 parent = str(parent) if self.revisionmap.get(parent) is None: self.convertrevision(parent) # TODO: If the parent is not converted, do it here. sys.exit("Parent revision {0} not converted" .format(parent)) self.hgclient.update(self.revisionmap[parent]) parent_filemap = self.revisions[parent].get("filemap") if parent_filemap is None: sys.exit("No parent filemap") parent_descriptor = self.prcs.descriptor(parent) parent_filemap = _makefilemap(parent_descriptor.files()) # Handles merges. mergeparents = descriptor.mergeparents() if mergeparents: self._handlemerge(mergeparents) # Makes the working directory clean. for i in self.hgclient.status(): if i[0] == "?": os.unlink(i[1]) self.hgclient.revert([], "null", all = True) self.prcs.checkout(version) files = descriptor.files() filemap = _makefilemap(files) self.revisions[version]["filemap"] = filemap # Checks for files. addlist = [] for name, file in files.iteritems(): # We cannot include symbolic links in Mercurial repositories. if "symlink" in file: if not self.symlink_warned.get(name, False): sys.stderr.write("{0}: warning: symbolic link\n" .format(name)) self.symlink_warned[name] = True else: file_id = file.get("id") if file_id is None: sys.exit("{0}: Missing file identity".format(name)) parent_name = parent_filemap.get(file_id) if parent_name is not None and parent_name != name: if self.verbose: sys.stderr.write("{0}: renamed from {1}\n" .format(name, parent_name)) self.hgclient.copy(parent_name, name, after = True) else: addlist.append(name) if addlist: self.hgclient.add(addlist) # Sets the branch for the following commit. version = descriptor.version() branch = "default" if not re.match("[0-9]+$", version.major): branch = version.major self.hgclient.branch(branch, force = True) version = str(version) message = descriptor.message() if not message: message = "(empty commit message)" revision = self.hgclient.commit(message = message, date = self.revisions[version]["date"], user = self.revisions[version]["author"]) self.revisionmap[version] = revision[1] # Keeps the revision identifier as a local tag for convenience. self.hgclient.tag([version], local = True, force = True) def _handlemerge(self, mergeparents): """Handle merges.""" if len(mergeparents) > 1: sys.stderr.write("warning: multiple merge parents: {0}\n" .format(join(mergeparents, ", "))) sys.stderr.write("warning: picked {0} on record\n" .format(mergeparents[-1])) self.hgclient.merge(self.revisionmap[mergeparents[-1]], tool = "internal:local", cb = hglib.merge.handlers.noninteractive)
class Converter(object): def __init__(self, name, verbose=False): """Construct a Converter object.""" self.name = name self.verbose = verbose self.revisionmap = {} self.symlink_warned = {} self.prcs = PrcsProject(self.name) self.revisions = self.prcs.revisions() self.hgclient = hglib.open(".") def convert(self): """Convert all revisions in a project.""" list = sorted(self.revisions, key=lambda id: self.revisions[id]["date"]) for i in list: self.convertrevision(i) def convertrevision(self, version): version = str(version) if self.revisions[version].get("deleted"): sys.stderr.write("Ignored deleted version {0}\n".format(version)) return if self.verbose: sys.stderr.write("Converting version {0}\n".format(version)) descriptor = self.prcs.descriptor(version) parent = descriptor.parentversion() if parent is None: # It is a root revision. self.hgclient.update("null") parent_filemap = {} else: while self.revisions[str(parent)].get("deleted"): parent.minor -= 1 parent = str(parent) if self.revisionmap.get(parent) is None: self.convertrevision(parent) # TODO: If the parent is not converted, do it here. sys.exit("Parent revision {0} not converted".format(parent)) self.hgclient.update(self.revisionmap[parent]) parent_filemap = self.revisions[parent].get("filemap") if parent_filemap is None: sys.exit("No parent filemap") parent_descriptor = self.prcs.descriptor(parent) parent_filemap = _makefilemap(parent_descriptor.files()) # Handles merges. mergeparents = descriptor.mergeparents() if mergeparents: self._handlemerge(mergeparents) # Makes the working directory clean. for i in self.hgclient.status(): if i[0] == "?": os.unlink(i[1]) self.hgclient.revert([], "null", all=True) self.prcs.checkout(version) files = descriptor.files() filemap = _makefilemap(files) self.revisions[version]["filemap"] = filemap # Checks for files. addlist = [] for name, file in files.iteritems(): # We cannot include symbolic links in Mercurial repositories. if "symlink" in file: if not self.symlink_warned.get(name, False): sys.stderr.write( "{0}: warning: symbolic link\n".format(name)) self.symlink_warned[name] = True else: file_id = file.get("id") if file_id is None: sys.exit("{0}: Missing file identity".format(name)) parent_name = parent_filemap.get(file_id) if parent_name is not None and parent_name != name: if self.verbose: sys.stderr.write("{0}: renamed from {1}\n".format( name, parent_name)) self.hgclient.copy(parent_name, name, after=True) else: addlist.append(name) if addlist: self.hgclient.add(addlist) # Sets the branch for the following commit. version = descriptor.version() branch = "default" if not re.match("[0-9]+$", version.major): branch = version.major self.hgclient.branch(branch, force=True) version = str(version) message = descriptor.message() if not message: message = "(empty commit message)" revision = self.hgclient.commit(message=message, date=self.revisions[version]["date"], user=self.revisions[version]["author"]) self.revisionmap[version] = revision[1] # Keeps the revision identifier as a local tag for convenience. self.hgclient.tag([version], local=True, force=True) def _handlemerge(self, mergeparents): """Handle merges.""" if len(mergeparents) > 1: sys.stderr.write("warning: multiple merge parents: {0}\n".format( join(mergeparents, ", "))) sys.stderr.write("warning: picked {0} on record\n".format( mergeparents[-1])) self.hgclient.merge(self.revisionmap[mergeparents[-1]], tool="internal:local", cb=hglib.merge.handlers.noninteractive)
class prcs_source(converter_source): """Import a PRCS project.""" def __init__(self, ui, path=None, rev=None): super(prcs_source, self).__init__(ui, path, rev) try: self._prcs = PrcsProject(path) self._revisions = self._prcs.revisions() except PrcsCommandError as error: ui.note(error.error_message) raise NoRepo() except PrcsError: raise NoRepo() self._cached_descriptor = {} def _descriptor(self, version): """Return a revision descriptor with caching.""" if not isinstance(version, str): version = str(version) if self._cached_descriptor.has_key(version): return self._cached_descriptor[version] descriptor = self._prcs.descriptor(version) self._cached_descriptor[version] = descriptor return descriptor def _nearest_ancestor(self, version): """Return an indirect parent for a deleted version.""" if version is None: return None if isinstance(version, str): version = PrcsVersion(version) deleted = False while self._revisions[str(version)]['deleted']: self.ui.note(version, " is deleted\n") deleted = True version.minor -= 1 if version.minor == 0: self.ui.note("No more ancestors on branch ", version.major) return None if deleted: self.ui.note("substituting ", version, "\n") return version def getheads(self): last_minor_version = {} for v in self._revisions.iterkeys(): if not self._revisions[v]['deleted']: v = PrcsVersion(v) if last_minor_version.get(v.major, 0) < v.minor: last_minor_version[v.major] = v.minor return map( lambda item: str(PrcsVersion(item[0], item[1])), last_minor_version.iteritems()) def getfile(self, name, version): self.ui.debug("prcs_source.getfile: ", name, " ", version, "\n") revision = self._revisions[version] descriptor = self._descriptor(version) files = descriptor.files() try: a = files[name] if a.has_key('symlink'): return (a['symlink'], 'l') self._prcs.checkout(version, [name]) file = open(name, 'rb') content = file.read() file.close() # NOTE: Win32 does not always releases the file name. if sys.platform != 'win32': os.unlink(name) dir = os.path.dirname(name) if dir: os.removedirs(dir) return (content, 'x' if a['mode'] & (0x1 << 6) else '') except KeyError: # The file with the specified name was deleted. raise IOError() def getchanges(self, version, full=False): self.ui.debug("prcs_source.getchanges: ", version, "\n") revision = self._revisions[version] descriptor = self._descriptor(version) files = [] copies = {} f = descriptor.files() p = descriptor.parentversion() # Preparing for a deleted parent. p = self._nearest_ancestor(p) if full or p is None: # This is the initial checkin so all files are affected. for name in f.iterkeys(): files.append((name, version)) else: pf = self._descriptor(p).files() # Handling added or changed files. for name, a in f.iteritems(): if pf.has_key(name): pa = pf[name] if a.has_key('symlink'): if not pa.has_key('symlink'): # Changed from a regular file to a symlink. files.append((name, version)) elif pa.has_key('symlink'): # Changed from a symlink to a regular file. files.append((name, version)) elif a['id'] != pa['id'] \ or a['revision'] != pa['revision'] \ or (a['mode'] ^ pa['mode']) & (0x1 << 6): files.append((name, version)) else: # Added. files.append((name, version)) # Handling deleted or renamed files. pnamebyid = {} for pname, pa in pf.iteritems(): if not f.has_key(pname): # Removed (or renamed). files.append((pname, version)) if not pa.has_key('symlink'): pnamebyid[pa['id']] = pname # Handling renamed files for copies. for name, a in f.iteritems(): if not a.has_key('symlink') and \ pnamebyid.has_key(a['id']): pname = pnamebyid[a['id']] if name != pname: self.ui.note(pname, " was renamed to ", name, "\n") copies[name] = pname return (files, copies) def getcommit(self, version): self.ui.debug("prcs_source.getcommit: ", version, "\n") revision = self._revisions[version] descriptor = self._descriptor(version) parents = [] p = descriptor.parentversion() # Preparing for a deleted parent. p = self._nearest_ancestor(p) if p is not None: parents.append(str(p)) for mp in descriptor.mergeparents(): # Preparing for a deleted merge parent. mp = self._nearest_ancestor(mp) if mp is not None: parents.append(str(mp)) branch = PrcsVersion(version).major if _MAIN_BRANCH_RE.match(branch): branch = None return commit( revision['author'], revision['date'].isoformat(" "), descriptor.message(), parents, branch) def gettags(self): """Return an empty dictionary since PRCS has no tags.""" return {}