Example #1
0
def clone(source=None,
          dest=None,
          noupdate=False,
          updaterev=None,
          rev=None,
          branch=None,
          pull=False,
          uncompressed=False,
          ssh=None,
          remotecmd=None,
          insecure=False,
          encoding=None,
          configs=None):
    args = util.cmdbuilder('clone',
                           source,
                           dest,
                           noupdate=noupdate,
                           updaterev=updaterev,
                           rev=rev,
                           branch=branch,
                           pull=pull,
                           uncompresses=uncompressed,
                           e=ssh,
                           remotecmd=remotecmd,
                           insecure=insecure)

    args.insert(0, HGPATH)
    proc = util.popen(args)
    out, err = proc.communicate()
    if proc.returncode:
        raise error.CommandError(args, proc.returncode, out, err)

    return client.hgclient(dest, encoding, configs, connect=False)
Example #2
0
    def unbundle(self,
                 file,
                 update=False,
                 ssh=None,
                 remotecmd=None,
                 insecure=False):
        """
        Apply one or more compressed changegroup files generated by the bundle
        command.

        Returns True on success, False if an update has unresolved files.
            file - source file name
            update - update to new branch head if changesets were unbundled
            ssh - specify ssh command to use
            remotecmd - specify hg command to run on the remote side
            insecure - do not verify server certificate (ignoring web.cacerts
                       config)
        """
        args = util.cmdbuilder('unbundle',
                               file,
                               u=update,
                               e=ssh,
                               remotecmd=remotecmd,
                               insecure=insecure)
        eh = util.reterrorhandler(args)
        self.rawcommand(args, eh=eh)

        return bool(eh)
Example #3
0
    def purge(self,
              dirs=None,
              all=False,
              include=None,
              exclude=None,
              p=False,
              abortonerr=False):
        """
        aliases: clean

        removes files not tracked by Mercurial

        Delete files not known to Mercurial. This is useful to test local and
        uncommitted changes in an otherwise-clean source tree.

        This means that purge will delete:

        - Unknown files: files marked with "?" by "hg status"
        - Empty directories: in fact Mercurial ignores directories unless they
          contain files under source control management

        But it will leave untouched:

        - Modified and unmodified tracked files
        - Ignored files (unless --all is specified)
        - New files added to the repository (with "hg add")

        If directories are given on the command line, only files in these
        directories are considered.

        Be careful with purge, as you could irreversibly delete some files you
        forgot to add to the repository. If you only want to print the list of
        files that this program would delete, use the --print option.

        Return True on success

        all - purge ignored files too
        include - include names matching the given patterns
        exclude - exclude names matching the given patterns
        abortonerror - abort if an error occurs
        p - print filenames instead of deleting them
        """
        if not isinstance(dirs, list):
            dirs = [dirs]

        args = util.cmdbuilder('purge',
                               all=all,
                               I=include,
                               X=exclude,
                               p=p,
                               a=abortonerr,
                               *dirs)
        args.extend(['--config', 'extensions.hgext.purge='])

        eh = util.reterrorhandler(args)
        self.rawcommand(args, eh=eh)

        return bool(eh)
Example #4
0
    def main(self):
        args = cmdbuilder(
            b('annotate'), self.client.root(), d=True, u=True, T='json')
        blame_json = ''.join(self.client.rawcommand(args))
        file_blames = json.loads(blame_json)

        for file_blame in file_blames:
            self.handleFile(file_blame)

        return {'authors': self.users,
                'blame': self.blame}
def _get_touched_files(hg_repo, commit_node):
    # Build list of files touched by this commit.

    def strip_servo(filename):
        assert filename.startswith('servo/')
        return filename[len('servo/'):]

    # Grab a list of files under the servo/ directory touched by this
    # change.
    args = cmdbuilder('log', template='{join(files,"\n")}',
                      r=commit_node, I='path:servo/')
    return map(strip_servo, hg_repo.rawcommand(args).split('\n'))
Example #6
0
def init(dest=None, ssh=None, remotecmd=None, insecure=False,
         encoding=None, configs=None):
    args = util.cmdbuilder('init', dest, e=ssh, remotecmd=remotecmd,
                           insecure=insecure)

    args.insert(0, HGPATH)
    proc = util.popen(args)
    out, err = proc.communicate()
    if proc.returncode:
        raise error.CommandError(args, proc.returncode, out, err)

    return client.hgclient(dest, encoding, configs, connect=False)
Example #7
0
    def churn(self, revrange=None, date=None, template=None, dateformat=None,
              files=[], changesets=False,
              sort=None, include=None, exclude=None):
        """
        histogram of changes to the repository

        This command will display a histogram representing the number of
        changed lines or revisions, grouped according to the given template.
        The default template will group changes by author. The --dateformat
        option may be used to group the results by date instead.

        Statistics are based on the number of changed lines, or alternatively
        the number of matching revisions if the --changesets option is
        specified.

        Examples:

          # display count of changed lines for every committer
          hg churn -t '{author|email}'

          # display daily activity graph
          hg churn -f '%H' -s -c

          # display activity of developers by month
          hg churn -f '%Y-%m' -s -c

          # display count of lines changed in every year
          hg churn -f '%Y' -s

        It is possible to map alternate email addresses to a main address by
        providing a file using the following format:

          <alias email> = <actual email>

        Such a file may be specified with the --aliases option, otherwise a
        .hgchurn file will be looked for in the working directory root.

        revrange          count rate for the specified revision or range
        date              count rate for revisions matching date spec
        template TEMPLATE  to group changesets (default: {author|email})
        dateformat FORMAT strftime-compatible format for grouping by date
        changesets count rate by number of changesets
        sort sort by key (default: sort by count)
        include include names matching the given patterns
        exclude  exclude names matching the given patterns
        """
        args = util.cmdbuilder('churn',
                               r=revrange, c=changesets, t=template,
                               f=dateformat, s=sort,
                               d=date, I=include, X=exclude, *files)
        args.extend(['--config', 'extensions.hgext.churn='])
        return self.rawcommand(args)
Example #8
0
    def main(self):
        args = cmdbuilder(b('annotate'),
                          self.client.root(),
                          d=True,
                          u=True,
                          T='json')
        blame_json = ''.join(self.client.rawcommand(args))
        file_blames = json.loads(blame_json)

        for file_blame in file_blames:
            self.handleFile(file_blame)

        return {'authors': self.users, 'blame': self.blame}
Example #9
0
    def attribution(self, file_paths):
        args = cmdbuilder(b('annotate'),
                          *[b(p) for p in file_paths],
                          template='json',
                          date=True,
                          user=True,
                          cwd=self.client.root())
        blame_json = self.client.rawcommand(args)
        file_blames = json.loads(blame_json)

        for file_blame in file_blames:
            self.handleFile(file_blame)

        return {'authors': self.users, 'blame': self.blame}
Example #10
0
def clone(source=None, dest=None, noupdate=False, updaterev=None, rev=None,
          branch=None, pull=False, uncompressed=False, ssh=None, remotecmd=None,
          insecure=False, encoding=None, configs=None):
    args = util.cmdbuilder('clone', source, dest, noupdate=noupdate,
                           updaterev=updaterev, rev=rev, branch=branch,
                           pull=pull, uncompressed=uncompressed,
                           e=ssh, remotecmd=remotecmd, insecure=insecure)

    args.insert(0, HGPATH)
    proc = util.popen(args)
    out, err = proc.communicate()
    if proc.returncode:
        raise error.CommandError(args, proc.returncode, out, err)

    return client.hgclient(dest, encoding, configs, connect=False)
Example #11
0
    def purge(self, dirs=None, all=False, include=None, exclude=None, p=False,
              abortonerr=False):
        """
        aliases: clean

        removes files not tracked by Mercurial

        Delete files not known to Mercurial. This is useful to test local and
        uncommitted changes in an otherwise-clean source tree.

        This means that purge will delete:

        - Unknown files: files marked with "?" by "hg status"
        - Empty directories: in fact Mercurial ignores directories unless they
          contain files under source control management

        But it will leave untouched:

        - Modified and unmodified tracked files
        - Ignored files (unless --all is specified)
        - New files added to the repository (with "hg add")

        If directories are given on the command line, only files in these
        directories are considered.

        Be careful with purge, as you could irreversibly delete some files you
        forgot to add to the repository. If you only want to print the list of
        files that this program would delete, use the --print option.

        Return True on success

        all - purge ignored files too
        include - include names matching the given patterns
        exclude - exclude names matching the given patterns
        abortonerror - abort if an error occurs
        p - print filenames instead of deleting them
        """
        if not isinstance(dirs, list):
            dirs = [dirs]

        args = util.cmdbuilder(
            'purge', all=all, I=include, X=exclude, p=p, a=abortonerr, *dirs)
        args.extend(['--config', 'extensions.hgext.purge='])

        eh = util.reterrorhandler(args)
        self.rawcommand(args, eh=eh)

        return bool(eh)
Example #12
0
def compare(sourceBranch="default", targetBranch="stable"):
    excludeFile = None
    excludes = []
    if os.path.isfile('graft_exclude.conf'):
        excludeFile = 'graft_exclude.conf'
    elif os.path.isfile('buildscripts/graft_exclude.conf'):
        excludeFile = 'buildscripts/graft_exclude.conf'

    if excludeFile:
        for L in open(excludeFile, 'r'):
            L = L.strip()
            if L:
                if L.startswith('#'):
                    continue
                Ls = L.split()
                if len(Ls[0]) > 12:
                    Ls[0] = Ls[0][:12]
                excludes.append(Ls[0])
        print('Loaded %s exclusions from %s\n' % (len(excludes), excludeFile))

    try:
        # Try if cwd is buildscripts/ folder
        c = hglib.open('../')
    except:
        # Try whether we are in hg root folder
        c = hglib.open('.')

    # Difference in changesets between branches
    cDiff = c.log("ancestors(%s) and not ancestors(%s)" %
                  (sourceBranch, targetBranch))

    # Filter out already grafted commits
    stdOut = c.rawcommand(cmdbuilder('log', debug=True, b=targetBranch))
    grafted = []
    r = re.compile('.*source=([a-zA-Z0-9]*)')
    for outL in stdOut.split('\n'):
        if outL.strip().startswith('extra') and ' source=' in outL:
            sourceRev = r.match(outL).groups()[0]
            grafted.append(sourceRev)

    # Filtered result
    # Also filter out merge commits (which are skipped by graft anyway)
    return [cs for cs in cDiff if (cs.node not in grafted and \
                                   cs.node[:12] not in excludes and \
                                   not isMergeCommit(c, cs) )]
Example #13
0
def compare(sourceBranch="default", targetBranch="stable"):
    excludeFile = None
    excludes = []
    if os.path.isfile('graft_exclude.conf'):
        excludeFile = 'graft_exclude.conf'
    elif os.path.isfile('buildscripts/graft_exclude.conf'):
        excludeFile = 'buildscripts/graft_exclude.conf'

    if excludeFile:
        for L in open(excludeFile, 'r'):
            L = L.strip()
            if L:
                if L.startswith('#'):
                    continue
                Ls = L.split()
                if len(Ls[0]) > 12:
                    Ls[0] = Ls[0][:12]
                excludes.append(Ls[0])
        print 'Loaded %s exclusions from %s\n' % (len(excludes), excludeFile)

    try:
        # Try if cwd is buildscripts/ folder
        c = hglib.open('../')
    except:
        # Try whether we are in hg root folder
        c = hglib.open('.')

    # Difference in changesets between branches
    cDiff = c.log("ancestors(%s) and not ancestors(%s)" % (sourceBranch, targetBranch))

    # Filter out already grafted commits
    stdOut = c.rawcommand(cmdbuilder('log', debug=True, b=targetBranch))
    grafted = []
    r = re.compile('.*source=([a-zA-Z0-9]*)')
    for outL in stdOut.split('\n'):
        if outL.strip().startswith('extra') and ' source=' in outL:
            sourceRev = r.match(outL).groups()[0]
            grafted.append(sourceRev)

    # Filtered result
    # Also filter out merge commits (which are skipped by graft anyway)
    return [cs for cs in cDiff if (cs.node not in grafted and \
                                   cs.node[:12] not in excludes and \
                                   not isMergeCommit(c, cs) )]
Example #14
0
    def commit(self, paths, op_meta):
        if 'message' not in op_meta or not op_meta['message']:
            raise ValueError("No commit message specified.")

        kwargs = {}
        if 'author' in op_meta:
            kwargs['u'] = _b(op_meta['author'])
        try:
            # We need to write our own command because somehow the `commit`
            # method in `hglib` doesn't support specifying the file(s)
            # directly -- only with `--include`. Weird.
            args = cmdbuilder(
                    b'commit', *_b(paths),
                    debug=True, m=_b(op_meta['message']), A=True,
                    **kwargs)
            self.client.rawcommand(args)
        except CommandError as e:
            raise SourceControlError('commit', str(e), _s(e.args),
                                     _s(e.out))
Example #15
0
    def get_file_contents(self, path, revision=None):
        # Note: Should ideally use the library's "cat" function, but it
        # has a bug in that it doesn't provide a "cwd" argument. This implementation
        # is based on the library's with the fix implemented.
        from hglib.util import b, cmdbuilder
        if path is not None:
            path = b(str(path))
        if revision is not None:
            revision = b(str(revision))

        files = [path]

        args = cmdbuilder(b('cat'),
                          r=revision,
                          o=None,
                          cwd=self.path,
                          hidden=self.client.hidden,
                          *files)
        print("hg " + ' '.join([x.decode() for x in args]))
        return BytesIO(self.client.rawcommand(args))
Example #16
0
    def unbundle(self, file, update=False, ssh=None, remotecmd=None,
                 insecure=False):
        """
        Apply one or more compressed changegroup files generated by the bundle
        command.

        Returns True on success, False if an update has unresolved files.
            file - source file name
            update - update to new branch head if changesets were unbundled
            ssh - specify ssh command to use
            remotecmd - specify hg command to run on the remote side
            insecure - do not verify server certificate (ignoring web.cacerts
                       config)
        """
        args = util.cmdbuilder(
            'unbundle', file,
            u=update, e=ssh, remotecmd=remotecmd, insecure=insecure)
        eh = util.reterrorhandler(args)
        self.rawcommand(args, eh=eh)

        return bool(eh)
Example #17
0
 def handleFile(self, leaf):
     try:
         parser = getParser(leaf)
     except UserWarning:
         return
     args = cmdbuilder(b('annotate'), d=True, u=True, T='json',
                       *['path:' + leaf])
     blame_json = ''.join(self.client.rawcommand(args))
     blames = json.loads(blame_json)
     fname = os.path.join(self.client.root(), leaf)
     parser.readFile(fname)
     entities, emap = parser.parse()
     self.blame[leaf] = {}
     for e in entities:
         blines = blames[(e.value_position()[0] - 1):e.value_position(-1)[0]]
         blines.sort(key=lambda blame: -blame['date'][0])  # ignore timezone
         blame = blines[0]
         user = blame['user']
         timestamp = blame['date'][0]  # ignore timezone
         if user not in self.users:
             self.users.append(user)
         userid = self.users.index(user)
         self.blame[leaf][e.key] = [userid, timestamp]
Example #18
0
    if args.get('graft', False):
        import subprocess

    try:
        # Try if cwd is buildscripts/ folder
        c = hglib.open('../')
    except:
        # Try whether we are in hg root folder
        c = hglib.open('.')

    # Difference in changesets between branches
    cDiff = c.log("ancestors(%s) and not ancestors(%s)" %
                  (sourceBranch, targetBranch))

    # Filter out already grafted commits
    stdOut = c.rawcommand(cmdbuilder('log', debug=True, b=targetBranch))
    grafted = []
    r = re.compile('.*source=([a-zA-Z0-9]*)')
    for outL in stdOut.split('\n'):
        if outL.strip().startswith('extra') and ' source=' in outL:
            sourceRev = r.match(outL).groups()[0]
            grafted.append(sourceRev)

    # Filtered result
    # Also filter out merge commits (which are skipped by graft anyway)
    return [cs for cs in cDiff if (cs.node not in grafted and \
                                   cs.node[:12] not in excludes and \
                                   not isMergeCommit(c, cs) )]


def formatChangeset(cs):
Example #19
0
    def churn(self,
              revrange=None,
              date=None,
              template=None,
              dateformat=None,
              files=[],
              changesets=False,
              sort=None,
              include=None,
              exclude=None):
        """
        histogram of changes to the repository

        This command will display a histogram representing the number of
        changed lines or revisions, grouped according to the given template.
        The default template will group changes by author. The --dateformat
        option may be used to group the results by date instead.

        Statistics are based on the number of changed lines, or alternatively
        the number of matching revisions if the --changesets option is
        specified.

        Examples:

          # display count of changed lines for every committer
          hg churn -t '{author|email}'

          # display daily activity graph
          hg churn -f '%H' -s -c

          # display activity of developers by month
          hg churn -f '%Y-%m' -s -c

          # display count of lines changed in every year
          hg churn -f '%Y' -s

        It is possible to map alternate email addresses to a main address by
        providing a file using the following format:

          <alias email> = <actual email>

        Such a file may be specified with the --aliases option, otherwise a
        .hgchurn file will be looked for in the working directory root.

        revrange          count rate for the specified revision or range
        date              count rate for revisions matching date spec
        template TEMPLATE  to group changesets (default: {author|email})
        dateformat FORMAT strftime-compatible format for grouping by date
        changesets count rate by number of changesets
        sort sort by key (default: sort by count)
        include include names matching the given patterns
        exclude  exclude names matching the given patterns
        """
        args = util.cmdbuilder('churn',
                               r=revrange,
                               c=changesets,
                               t=template,
                               f=dateformat,
                               s=sort,
                               d=date,
                               I=include,
                               X=exclude,
                               *files)
        args.extend(['--config', 'extensions.hgext.churn='])
        return self.rawcommand(args)
def _get_touched_files(hg_repo, commit_node):
    # Grab a list of files under the servo/ directory touched by this
    # change, stripping the leading servo/ prefix.
    args = cmdbuilder('log', template='{join(files,"\n")}', r=commit_node)
    files = hg_repo.rawcommand(args).split('\n')
    return [fn[len('servo/'):] for fn in files if fn.startswith('servo/')]