Esempio n. 1
0
    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(".")
Esempio n. 2
0
    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(".")
Esempio n. 3
0
    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 = {}
Esempio n. 4
0
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)
Esempio n. 5
0
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)
Esempio n. 6
0
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 {}