Esempio n. 1
0
def new_commit(orig_commit, ui, repo, *pats, **opts):
    if opts['message'] or opts['logfile']:
        # don't act if user already specified a message
        return orig_commit(ui, repo, *pats, **opts)

    # check if changelog changed
    logname = ui.config('changelog', 'filename', 'CHANGES')
    if pats:
        match = cmdutil.match(repo, pats, opts)
        if logname not in match:
            # changelog is not mentioned
            return orig_commit(ui, repo, *pats, **opts)
    logmatch = cmdutil.match(repo, [logname], {})
    logmatch.bad = lambda f, msg: None  # don't complain if file is missing

    # get diff of changelog
    log = []
    for chunk in patch.diff(repo, None, None, match=logmatch):
        for line in chunk.splitlines():
            # naive: all added lines are the changelog
            if line.startswith('+') and not line.startswith('+++'):
                log.append(line[1:].rstrip().expandtabs())
    log = normalize_log(log)

    # always let the user edit the message
    opts['force_editor'] = True
    opts['message'] = log
    return orig_commit(ui, repo, *pats, **opts)
Esempio n. 2
0
def perfwalk(ui, repo, *pats):
    try:
        m = cmdutil.match(repo, pats, {})
        timer(lambda: len(list(repo.dirstate.walk(m, True, False))))
    except:
        try:
            m = cmdutil.match(repo, pats, {})
            timer(lambda: len([b for a,b,c in repo.dirstate.statwalk([], m)]))
        except:
            timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
Esempio n. 3
0
def perfwalk(ui, repo, *pats):
    try:
        m = cmdutil.match(repo, pats, {})
        timer(lambda: len(list(repo.dirstate.walk(m, [], True, False))))
    except:
        try:
            m = cmdutil.match(repo, pats, {})
            timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)]))
        except:
            timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
Esempio n. 4
0
 def add(self, filepaths, dry_run=False, subrepo=None):
     "add the specified files on the next commit"
     m = match(self.repo, filepaths)
     prefix = ""
     uio = self.repo.ui
     rejected = cmdutil.add(uio, self.repo, m, dry_run, subrepo, prefix)
     return rejected
Esempio n. 5
0
    def cleanup(self, repo, pats, opts):
        '''removes all changes from the working copy and makes it so
        there isn't a patch applied'''

        # find added files in the user's chosen set
        m = cmdutil.match(repo, pats, opts)
        added = repo.status(match=m)[1]

        revertopts = {
            'include': opts.get('include'),
            'exclude': opts.get('exclude'),
            'date': None,
            'all': True,
            'rev': '.',
            'no_backup': True,
        }
        self.ui.pushbuffer()  # silence revert
        try:
            commands.revert(self.ui, repo, *pats, **revertopts)

            # finish the job of reverting added files (safe because they are
            # saved in the attic patch)
            for fn in added:
                self.ui.status(_('removing %s\n') % fn)
                util.unlink(fn)
        finally:
            self.ui.popbuffer()

        self.applied = ''
        self.persiststate()
Esempio n. 6
0
    def search_thread(self, q, tgts, copy):
        hglib.invalidaterepo(self.repo)
        srcs = []
        audit_path = util.path_auditor(self.repo.root)
        m = cmdutil.match(self.repo)
        for abs in self.repo.walk(m):
            target = self.repo.wjoin(abs)
            good = True
            try:
                audit_path(abs)
            except:
                good = False
            status = self.repo.dirstate[abs]
            if (not good or not os.path.lexists(target)
                or (os.path.isdir(target) and not os.path.islink(target))):
                srcs.append(abs)
            elif copy and status == 'n':
                # looking for copies, so any revisioned file is a
                # potential source (yes, this will be expensive)
                # Added and removed files are not considered as copy
                # sources.
                srcs.append(abs)
        if copy:
            simularity = 1.0
        else:
            simularity = self.adjustment.get_value() / 100.0;

        gen = similar.findrenames(self.repo, tgts, srcs, simularity)
        for old, new, score in gen:
            q.put( [old, new, '%d%%' % (score*100)] )
Esempio n. 7
0
def _casecollide(ui, repo, *pats, **opts):
    '''check the case of the given file against the repository. Return True
    on collisions and (optionally) print a list of problem-files.'''
    reserved = False
    colliding = False
    casefold = False

    override = opts['override'] or ui.configbool('caseguard', 'override')
    nowinchk = opts['nowincheck'] or ui.configbool('caseguard', 'nowincheck')

    if len(set(s.lower() for s in pats)) != len(pats):
        colliding = True
        ui.note(_('file list contains a possible case-fold collision\n'))

    added = repo.status()[1] + repo.status()[3]
    exclst = [item[0] for item in repo['.'].manifest().iteritems()] + added
    chklst = [item.lower() for item in exclst]
    mtch = dict(zip(chklst, exclst))
    m = cmdutil.match(repo, pats, opts)

    for f in repo.walk(m):
        flwr = f.lower()
        reserved = _wincheck(ui, f) or _charcheck(ui, f) or reserved
        if f not in repo.dirstate and f not in exclst and flwr in mtch:
            colliding = True
            ui.note(_('adding %s may cause a case-fold collision with %s\n') %
                (f, mtch[flwr]))

        mtch[flwr] = f

    casefold = not override and ((reserved and not nowinchk) or colliding)

    return casefold, colliding, reserved and not nowinchk
Esempio n. 8
0
def autodiff(ui, repo, *pats, **opts):
    diffopts = patch.diffopts(ui, opts)
    git = opts.get('git', 'no')
    brokenfiles = set()
    losedatafn = None
    if git in ('yes', 'no'):
        diffopts.git = git == 'yes'
        diffopts.upgrade = False
    elif git == 'auto':
        diffopts.git = False
        diffopts.upgrade = True
    elif git == 'warn':
        diffopts.git = False
        diffopts.upgrade = True
        def losedatafn(fn=None, **kwargs):
            brokenfiles.add(fn)
            return True
    elif git == 'abort':
        diffopts.git = False
        diffopts.upgrade = True
        def losedatafn(fn=None, **kwargs):
            raise util.Abort('losing data for %s' % fn)
    else:
        raise util.Abort('--git must be yes, no or auto')

    node1, node2 = cmdutil.revpair(repo, [])
    m = cmdutil.match(repo, pats, opts)
    it = patch.diff(repo, node1, node2, match=m, opts=diffopts,
                    losedatafn=losedatafn)
    for chunk in it:
        ui.write(chunk)
    for fn in sorted(brokenfiles):
        ui.write('data lost for: %s\n' % fn)
def impl_hg_tree(repo, cid, path, names, *args):
    m = cmdutil.match(repo, pats=[path], default=path)
    data = {}
    for name in names:
        rev_iter = cmdutil.walkchangerevs(repo, m, {'rev': cid}, lambda c,f: None)
        data[name] = rev_iter.next().hex()
    return data
Esempio n. 10
0
 def add(self, filepaths, dry_run=False, subrepo=None):
     "add the specified files on the next commit"
     m = match(self.repo, filepaths)
     prefix = ""
     uio = self.repo.ui
     rejected = cmdutil.add(uio, self.repo, m, dry_run, subrepo, prefix)
     return rejected
Esempio n. 11
0
    def _get_history_1_4(self, repo, pats, opts, limit):
        matcher = cmdutil.match(repo, pats, opts)
        if self.isfile:
            fncache = {}
            def prep(ctx, fns):
                if self.isfile:
                    fncache[ctx.rev()] = fns[0]
        else:
            def prep(ctx, fns):
                pass

        # keep one lookahead entry so that we can detect renames
        path = self.path
        entry = None
        count = 1
        for ctx in cmdutil.walkchangerevs(repo, matcher, opts, prep):
            if self.isfile and entry:
                path = fncache[ctx.rev()]
                if path != entry[0]:
                    entry = entry[0:2] + (Changeset.COPY,)
            if entry:
                count += 1
                yield entry
            entry = (path, self.repos.hg_display(ctx.node()), Changeset.EDIT)
        if entry:
            if count < limit:
                entry = entry[0:2] + (Changeset.ADD,)
            yield entry
Esempio n. 12
0
 def createpatch(self, repo, name, msg, user, date, pats=[], opts={}):
     """creates a patch from the current state of the working copy"""
     fp = self.opener(name, 'w')
     ctx = repo[None]
     fp.write('# HG changeset patch\n')
     if user:
         fp.write('# User %s\n' % user)
     if date:
         fp.write('# Date %d %d\n' % date)
     parents = [p.node() for p in ctx.parents() if p]
     if parents and parents[0]:
         fp.write('# Parent  %s\n' % hex(parents[0]))
     if msg:
         if not isinstance(msg, str):
             msg = '\n'.join(msg)
         if msg and msg[-1] != '\n':
             msg += '\n'
         fp.write(msg)
     m = cmdutil.match(repo, pats, opts)
     chunks = patch.diff(repo, match = m, opts = self.diffopts(opts))
     for chunk in chunks:
         fp.write(chunk)
     fp.close()
     self.currentpatch=name
     self.persiststate()
Esempio n. 13
0
 def createpatch(self, repo, name, msg, user, date, pats=[], opts={}):
     """creates a patch from the current state of the working copy"""
     fp = self.opener(name, 'w')
     ctx = repo[None]
     fp.write('# HG changeset patch\n')
     if user:
         fp.write('# User %s\n' % user)
     if date:
         fp.write('# Date %d %d\n' % date)
     parents = [p.node() for p in ctx.parents() if p]
     if parents and parents[0]:
         fp.write('# Parent  %s\n' % hex(parents[0]))
     if msg:
         if not isinstance(msg, str):
             msg = '\n'.join(msg)
         if msg and msg[-1] != '\n':
             msg += '\n'
         fp.write(msg)
     m = cmdutil.match(repo, pats, opts)
     chunks = patch.diff(repo, match=m, opts=self.diffopts(opts))
     for chunk in chunks:
         fp.write(chunk)
     fp.close()
     self.currentpatch = name
     self.persiststate()
Esempio n. 14
0
def _casecollide(ui, repo, *pats, **opts):
    '''check the case of the given file against the repository. Return True
    on collisions and (optionally) print a list of problem-files.'''
    reserved = False
    colliding = False
    casefold = False

    override = opts['override'] or ui.configbool('caseguard', 'override')
    nowinchk = opts['nowincheck'] or ui.configbool('caseguard', 'nowincheck')

    if len(set(s.lower() for s in pats)) != len(pats):
        colliding = True
        ui.note(_('file list contains a possible case-fold collision\n'))

    added = repo.status()[1] + repo.status()[3]
    exclst = [item[0] for item in repo['.'].manifest().iteritems()] + added
    chklst = [item.lower() for item in exclst]
    mtch = dict(zip(chklst, exclst))
    m = cmdutil.match(repo, pats, opts)

    for f in repo.walk(m):
        flwr = f.lower()
        reserved = _wincheck(ui, f) or _charcheck(ui, f) or reserved
        if f not in repo.dirstate and f not in exclst and flwr in mtch:
            colliding = True
            ui.note(
                _('adding %s may cause a case-fold collision with %s\n') %
                (f, mtch[flwr]))

        mtch[flwr] = f

    casefold = not override and ((reserved and not nowinchk) or colliding)

    return casefold, colliding, reserved and not nowinchk
Esempio n. 15
0
    def cleanup(self, repo, pats, opts):
        '''removes all changes from the working copy and makes it so
        there isn't a patch applied'''

        # find added files in the user's chosen set
        m = cmdutil.match(repo, pats, opts)
        added = repo.status(match=m)[1]

        revertopts = { 'include': opts.get('include'),
                       'exclude': opts.get('exclude'),
                       'date': None,
                       'all': True,
                       'rev': '.',
                       'no_backup': True,
                     }
        self.ui.pushbuffer()            # silence revert
        try:
            commands.revert(self.ui, repo, *pats, **revertopts)

            # finish the job of reverting added files (safe because they are
            # saved in the attic patch)
            for fn in added:
                self.ui.status(_('removing %s\n') % fn)
                util.unlink(fn)
        finally:
            self.ui.popbuffer()

        self.applied = ''
        self.persiststate()
Esempio n. 16
0
def _modified_regions(repo, patterns, **kwargs):
    opt_all = kwargs.get('all', False)
    opt_no_ignore = kwargs.get('no_ignore', False)

    # Import the match (repository file name matching helper)
    # function. Different versions of Mercurial keep it in different
    # modules and implement them differently.
    try:
        from mercurial import scmutil
        m = scmutil.match(repo[None], patterns, kwargs)
    except ImportError:
        from mercurial import cmdutil
        m = cmdutil.match(repo, patterns, kwargs)

    modified, added, removed, deleted, unknown, ignore, clean = \
        repo.status(match=m, clean=opt_all)

    if not opt_all:
        try:
            wctx = repo.workingctx()
        except:
            from mercurial import context
            wctx = context.workingctx(repo)

        files = [ (fn, all_regions) for fn in added ] + \
            [ (fn,  modregions(wctx, fn)) for fn in modified ]
    else:
        files = [ (fn, all_regions) for fn in added + modified + clean ]

    for fname, mod_regions in files:
        if opt_no_ignore or not check_ignores(fname):
            yield fname, mod_regions
Esempio n. 17
0
    def cacherepo(self, root, pats=[], filetypes="CI?"):
        status = ([],) * 7
        try:
            repo = hg.repository(ui.ui(), path=root)
            matcher = cmdutil.match(repo, pats)
            st = repo.status(match=matcher, clean="C" in filetypes, ignored="I" in filetypes, unknown="?" in filetypes)
        except IOError:
            pass
        filelist = []
        # concatenate status output into a single list, then sort on filename
        for l, s in ((st[0], "M"), (st[1], "A"), (st[2], "R"), (st[3], "!"), (st[4], "?"), (st[5], "I"), (st[6], "C")):
            for m in l:
                filelist.append([m, s])
        filelist.sort()

        # Build tree data structure
        modelroot = dirnode()
        for name, filestatus in filelist:
            dirs, basename = self.split(name)
            curdir = modelroot
            for dir in dirs:
                if dir not in curdir.subdirs:
                    curdir.addsubdir(dir)
                curdir.addstatus(filestatus)
                curdir = curdir.subdirs[dir]
            curdir.addfile(name, filestatus)

        self.cachedmodel = modelroot
        self.cachedroot = root
        self.cachedrepo = repo
Esempio n. 18
0
def qrefresh_wrapper(self, repo, *pats, **opts):
    mqmessage = opts.pop('mqmessage', None)
    mqcommit, q, r = mqcommit_info(self, repo, opts)

    diffstat = ""
    if mqcommit and mqmessage:
        if mqmessage.find("%s") != -1:
            buffer = StringIO.StringIO()
            m = cmdutil.match(repo, None, {})
            diffopts = mdiff.diffopts()
            cmdutil.diffordiffstat(self, repo, diffopts,
                                   repo.dirstate.parents()[0], None, m,
                                   stat=True, fp = buffer)
            diffstat = buffer.getvalue()
            buffer.close()

    mq.refresh(self, repo, *pats, **opts)

    if mqcommit and len(q.applied) > 0:
        patch = q.applied[-1].name
        if r is None:
            raise util.Abort("no patch repository found when using -Q option")
        mqmessage = mqmessage.replace("%p", patch)
        mqmessage = mqmessage.replace("%a", 'UPDATE')
        mqmessage = mqmessage.replace("%s", diffstat)
        commands.commit(r.ui, r, message=mqmessage)
Esempio n. 19
0
def _casecollide(ui, repo, *pats, **opts):
    '''check the case of the given file against the repository. Return True
    on collisions and (optionally) print a list of problem-files.'''
    override = opts['override'] or ui.configbool('caseguard', 'override')
    nowinchk = opts['nowincheck'] or ui.configbool('caseguard', 'nowincheck')

    loglevel = _defaultloglevel(ui, not override)

    if len(set(s.lower() for s in pats)) != len(pats):
        colliding = True
        ui.note(_('file list contains a possible case-fold collision\n'))

    added = repo.status()[1] + repo.status()[3]
    exclst = [item[0] for item in repo['.'].manifest().iteritems()] + added
    chklst = [item.lower() for item in exclst]
    mtch = dict(zip(chklst, exclst))
    m = cmdutil.match(repo, pats, opts)

    for f in repo.walk(m):
        flwr = f.lower()
        _wincheck(ui, f, loglevel)
        _charcheck(ui, f, loglevel)
        if f not in repo.dirstate and f not in exclst and flwr in mtch:
            loglevel(_('possible case-folding collision for %s') % f)
        mtch[flwr] = f
Esempio n. 20
0
def casecheck(ui, repo, *pats, **opts):
    if not repo.local():
        ui.note(_('Only local repositories can be checked'))
        return
    '''check an existing local repository for filename issues (caseguard)'''
    try:
        # Mercurial >= 1.9
        m = scmutil.match(repo[0], pats, opts)
    except ImportError:
        # Mercurial <= 1.8
        m = cmdutil.match(repo, pats, opts)

    seen = dict()

    def dostatus(msg):
        ui.status('%s\n' % msg)

    for f in repo.walk(m):
        if f in repo.dirstate:
            badname = _wincheck(ui, f, dostatus) or \
                        _charcheck(ui, f, dostatus)
            if f.lower() in seen:
                dostatus(_('%s collides with %s') % (f, seen[f.lower()]))
            else:
                seen[f.lower()] = f
                if not badname:
                    ui.note(_('\t[OK] %s\n') % f)
Esempio n. 21
0
def _modified_regions(repo, patterns, **kwargs):
    opt_all = kwargs.get('all', False)
    opt_no_ignore = kwargs.get('no_ignore', False)

    # Import the match (repository file name matching helper)
    # function. Different versions of Mercurial keep it in different
    # modules and implement them differently.
    try:
        from mercurial import scmutil
        m = scmutil.match(repo[None], patterns, kwargs)
    except ImportError:
        from mercurial import cmdutil
        m = cmdutil.match(repo, patterns, kwargs)

    modified, added, removed, deleted, unknown, ignore, clean = \
        repo.status(match=m, clean=opt_all)

    if not opt_all:
        try:
            wctx = repo.workingctx()
        except:
            from mercurial import context
            wctx = context.workingctx(repo)

        files = [ (fn, all_regions) for fn in added ] + \
            [ (fn,  modregions(wctx, fn)) for fn in modified ]
    else:
        files = [(fn, all_regions) for fn in added + modified + clean]

    for fname, mod_regions in files:
        if opt_no_ignore or not check_ignores(fname):
            yield fname, mod_regions
Esempio n. 22
0
def get_matcher(repo, pats=[], opts={}, showbad=True):
    '''Wrapper around cmdutil.match() that adds showbad: if false, neuter
    the match object\'s bad() method so it does not print any warnings
    about missing files or directories.'''
    match = cmdutil.match(repo, pats, opts)
    if not showbad:
        match.bad = lambda f, msg: None
    return match
Esempio n. 23
0
def impl_hg_tree(repo, cid, path, names, *args):
    m = cmdutil.match(repo, pats=[path], default=path)
    data = {}
    for name in names:
        rev_iter = cmdutil.walkchangerevs(
            repo, m, {'rev': cid}, lambda c, f: None)
        data[name] = rev_iter.next().hex()
    return data
Esempio n. 24
0
def get_matcher(repo, pats=[], opts={}, showbad=True):
    '''Wrapper around cmdutil.match() that adds showbad: if false, neuter
    the match object\'s bad() method so it does not print any warnings
    about missing files or directories.'''
    match = cmdutil.match(repo, pats, opts)
    if not showbad:
        match.bad = lambda f, msg: None
    return match
Esempio n. 25
0
def _status(ui, repo, kwt, *pats, **opts):
    '''Bails out if [keyword] configuration is not active.
    Returns status of working directory.'''
    if kwt:
        return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
                           unknown=opts.get('unknown') or opts.get('all'))
    if ui.configitems('keyword'):
        raise util.Abort(_('[keyword] patterns cannot match'))
    raise util.Abort(_('no [keyword] patterns configured'))
Esempio n. 26
0
 def commit(self, filepaths, message):
     "commit the specified files or all outstanding changes"
     oldid = self.repo[self.repo.lookup('.')]
     user = date = None
     m = match(self.repo, filepaths)
     node = self.repo.commit(message, user, date, m)
     if self.repo[self.repo.lookup('.')] == oldid:
         return None  # no changes
     return True  # sucess
Esempio n. 27
0
def _status(ui, repo, kwt, unknown, *pats, **opts):
    '''Bails out if [keyword] configuration is not active.
    Returns status of working directory.'''
    if kwt:
        match = cmdutil.match(repo, pats, opts)
        return repo.status(match=match, unknown=unknown, clean=True)
    if ui.configitems('keyword'):
        raise util.Abort(_('[keyword] patterns cannot match'))
    raise util.Abort(_('no [keyword] patterns configured'))
Esempio n. 28
0
def changedlines(ui, repo, ctx1, ctx2, fns):
    lines = 0
    fmatch = cmdutil.match(repo, pats=fns)
    diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
    for l in diff.split('\n'):
        if (l.startswith("+") and not l.startswith("+++ ")
                or l.startswith("-") and not l.startswith("--- ")):
            lines += 1
    return lines
Esempio n. 29
0
 def commit(self, filepaths, message):
     "commit the specified files or all outstanding changes"
     oldid = self.repo[self.repo.lookup('.')]
     user = date = None
     m = match(self.repo, filepaths)
     node = self.repo.commit(message, user, date, m)
     if self.repo[self.repo.lookup('.')] == oldid:
         return None # no changes
     return True # sucess
Esempio n. 30
0
def countrate(ui, repo, amap, *pats, **opts):
    """Calculate stats"""
    if opts.get('dateformat'):
        def getkey(ctx):
            t, tz = ctx.date()
            date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
            return date.strftime(opts['dateformat'])
    else:
        tmpl = opts.get('template', '{author|email}')
        tmpl = maketemplater(ui, repo, tmpl)
        def getkey(ctx):
            ui.pushbuffer()
            tmpl.show(ctx)
            return ui.popbuffer()

    state = {'count': 0, 'pct': 0}
    rate = {}
    df = False
    if opts.get('date'):
        df = util.matchdate(opts['date'])

    m = cmdutil.match(repo, pats, opts)
    def prep(ctx, fns):
        rev = ctx.rev()
        if df and not df(ctx.date()[0]): # doesn't match date format
            return

        key = getkey(ctx)
        key = amap.get(key, key) # alias remap
        if opts.get('changesets'):
            rate[key] = (rate.get(key, (0,))[0] + 1, 0)
        else:
            parents = ctx.parents()
            if len(parents) > 1:
                ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
                return

            ctx1 = parents[0]
            lines = changedlines(ui, repo, ctx1, ctx, fns)
            rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]

        if opts.get('progress'):
            state['count'] += 1
            newpct = int(100.0 * state['count'] / max(len(repo), 1))
            if state['pct'] < newpct:
                state['pct'] = newpct
                ui.write("\r" + _("generating stats: %d%%") % state['pct'])
                sys.stdout.flush()

    for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
        continue

    if opts.get('progress'):
        ui.write("\r")
        sys.stdout.flush()

    return rate
Esempio n. 31
0
 def cat(self, file1, revision=None):
     "return the current or given revision of a file"
     ctx = revsingle(self.repo, revision)
     m = match(self.repo, (file1, ))
     for abs in ctx.walk(m):
         data = ctx[abs].data()
         if self.decode:
             data = self.repo.wwritedata(abs, data)
         return data
Esempio n. 32
0
 def cat(self, file1, revision=None):
     "return the current or given revision of a file"
     ctx = revsingle(self.repo, revision)
     m = match(self.repo, (file1,))
     for abs in ctx.walk(m):
         data = ctx[abs].data()
         if self.decode:
             data = self.repo.wwritedata(abs, data)
         return data
Esempio n. 33
0
def changedlines(ui, repo, ctx1, ctx2, fns):
    lines = 0
    fmatch = cmdutil.match(repo, pats=fns)
    diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
    for l in diff.split('\n'):
        if (l.startswith("+") and not l.startswith("+++ ") or
            l.startswith("-") and not l.startswith("--- ")):
            lines += 1
    return lines
Esempio n. 34
0
def difftree(ui, repo, node1=None, node2=None, *files, **opts):
    """diff trees from two commits"""
    def __difftree(repo, node1, node2, files=[]):
        assert node2 is not None
        mmap = repo[node1].manifest()
        mmap2 = repo[node2].manifest()
        m = cmdutil.match(repo, files)
        modified, added, removed = repo.status(node1, node2, m)[:3]
        empty = short(nullid)

        for f in modified:
            # TODO get file permissions
            ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
                     (short(mmap[f]), short(mmap2[f]), f, f))
        for f in added:
            ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
                     (empty, short(mmap2[f]), f, f))
        for f in removed:
            ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
                     (short(mmap[f]), empty, f, f))

    ##

    while True:
        if opts['stdin']:
            try:
                line = raw_input().split(' ')
                node1 = line[0]
                if len(line) > 1:
                    node2 = line[1]
                else:
                    node2 = None
            except EOFError:
                break
        node1 = repo.lookup(node1)
        if node2:
            node2 = repo.lookup(node2)
        else:
            node2 = node1
            node1 = repo.changelog.parents(node1)[0]
        if opts['patch']:
            if opts['pretty']:
                catcommit(ui, repo, node2, "")
            m = cmdutil.match(repo, files)
            chunks = patch.diff(repo,
                                node1,
                                node2,
                                match=m,
                                opts=patch.diffopts(ui, {'git': True}))
            for chunk in chunks:
                ui.write(chunk)
        else:
            __difftree(repo, node1, node2, files=files)
        if not opts['stdin']:
            break
Esempio n. 35
0
def countrate(ui, repo, amap, *pats, **opts):
    """Calculate stats"""
    if opts.get('dateformat'):
        def getkey(ctx):
            t, tz = ctx.date()
            date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
            return date.strftime(opts['dateformat'])
    else:
        tmpl = opts.get('template', '{author|email}')
        tmpl = maketemplater(ui, repo, tmpl)
        def getkey(ctx):
            ui.pushbuffer()
            tmpl.show(ctx)
            return ui.popbuffer()

    state = {'count': 0}
    rate = {}
    df = False
    if opts.get('date'):
        df = util.matchdate(opts['date'])

    m = cmdutil.match(repo, pats, opts)
    def prep(ctx, fns):
        rev = ctx.rev()
        if df and not df(ctx.date()[0]): # doesn't match date format
            return

        key = getkey(ctx)
        key = amap.get(key, key) # alias remap
        key = key.strip() # ignore leading and trailing spaces
        if opts.get('changesets'):
            rate[key] = (rate.get(key, (0,))[0] + 1, 0)
        else:
            parents = ctx.parents()
            if len(parents) > 1:
                ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
                return

            ctx1 = parents[0]
            lines = changedlines(ui, repo, ctx1, ctx, fns)
            rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]

        state['count'] += 1
        ui.progress(_('analyzing'), state['count'], total=len(repo))

    for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
        continue

    ui.progress(_('analyzing'), None)

    return rate
Esempio n. 36
0
def difftree(ui, repo, node1=None, node2=None, *files, **opts):
    """diff trees from two commits"""
    def __difftree(repo, node1, node2, files=[]):
        assert node2 is not None
        mmap = repo[node1].manifest()
        mmap2 = repo[node2].manifest()
        m = cmdutil.match(repo, files)
        modified, added, removed  = repo.status(node1, node2, m)[:3]
        empty = short(nullid)

        for f in modified:
            # TODO get file permissions
            ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
                     (short(mmap[f]), short(mmap2[f]), f, f))
        for f in added:
            ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
                     (empty, short(mmap2[f]), f, f))
        for f in removed:
            ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
                     (short(mmap[f]), empty, f, f))
    ##

    while True:
        if opts['stdin']:
            try:
                line = raw_input().split(' ')
                node1 = line[0]
                if len(line) > 1:
                    node2 = line[1]
                else:
                    node2 = None
            except EOFError:
                break
        node1 = repo.lookup(node1)
        if node2:
            node2 = repo.lookup(node2)
        else:
            node2 = node1
            node1 = repo.changelog.parents(node1)[0]
        if opts['patch']:
            if opts['pretty']:
                catcommit(ui, repo, node2, "")
            m = cmdutil.match(repo, files)
            chunks = patch.diff(repo, node1, node2, match=m,
                                opts=patch.diffopts(ui, {'git': True}))
            for chunk in chunks:
                ui.write(chunk)
        else:
            __difftree(repo, node1, node2, files=files)
        if not opts['stdin']:
            break
Esempio n. 37
0
def find_files_with_lib(dirname):
    """
    Use the Mercurial library to recursively find versioned files in dirname.
    """
    try:
        try:
            repo = hg.repository(ui.ui(), path=dirname)
        except RepoError:
            return
        # tuple of (modified, added, removed, deleted, unknown, ignored, clean)
        modified, added, removed, deleted, unknown = repo.status()[:5]

        # exclude all files that hg knows about, but haven't been added,
        # or have been deleted, removed, or have an unknown status
        excluded = removed + deleted + unknown

        if version in OLD_VERSIONS:
            from mercurial import util
            node = None
            for src, abs, rel, exact in cmdutil.walk(repo, [], {},
                                                     node=node,
                                                     badmatch=util.always,
                                                     default='relglob'):
                if src == 'b':
                    continue
                if not node and abs not in repo.dirstate:
                    continue
                if abs in excluded:
                    continue
                yield abs
        else:
            rev = None
            try:
                match = cmdutil.match(repo, [], {}, default='relglob')
            except:
                # Probably mercurial 1.8+
                from mercurial import scmutil
                match = scmutil.match(repo[None], [], {}, default='relglob')

            match.bad = lambda x, y: False
            for abs in repo[rev].walk(match):
                if not rev and abs not in repo.dirstate:
                    continue
                if abs in excluded:
                    continue
                yield abs
    except Exception:
        if log:
            log.warn("Error in setuptools_hg: %s" % sys.exc_info()[1])
        # try calling hg command as a last resort
        find_files_with_cmd(dirname)
Esempio n. 38
0
def find_files_with_lib(dirname):
    """
    Use the Mercurial library to recursively find versioned files in dirname.
    """
    try:
        try:
            repo = hg.repository(ui.ui(), path=dirname)
        except RepoError:
            return
        # tuple of (modified, added, removed, deleted, unknown, ignored, clean)
        modified, added, removed, deleted, unknown = repo.status()[:5]

        # exclude all files that hg knows about, but haven't been added,
        # or have been deleted, removed, or have an unknown status
        excluded = removed + deleted + unknown

        if version in OLD_VERSIONS:
            from mercurial import util

            node = None
            for src, abs, rel, exact in cmdutil.walk(repo, [], {}, node=node, badmatch=util.always, default="relglob"):
                if src == "b":
                    continue
                if not node and abs not in repo.dirstate:
                    continue
                if abs in excluded:
                    continue
                yield abs
        else:
            rev = None
            try:
                match = cmdutil.match(repo, [], {}, default="relglob")
            except:
                # Probably mercurial 1.8+
                from mercurial import scmutil

                match = scmutil.match(repo[None], [], {}, default="relglob")

            match.bad = lambda x, y: False
            for abs in repo[rev].walk(match):
                if not rev and abs not in repo.dirstate:
                    continue
                if abs in excluded:
                    continue
                yield abs
    except Exception, e:
        if log:
            log.warn("Error in setuptools_hg: %s" % e)
        # try calling hg command as a last resort
        find_files_with_cmd(dirname)
Esempio n. 39
0
def getmatcher(repo, pats=[], opts={}, showbad=True):
    """Wrapper around scmutil.match() that adds showbad: if false, neuter
    the match object\'s bad() method so it does not print any warnings
    about missing files or directories."""
    try:
        # Mercurial >= 1.9
        match = scmutil.match(repo[None], pats, opts)
    except ImportError:
        # Mercurial <= 1.8
        match = cmdutil.match(repo, pats, opts)

    if not showbad:
        match.bad = lambda f, msg: None
    return match
Esempio n. 40
0
File: dv.py Progetto: dmayle/DVDev
    def _get_diffs(self, repository=None, filepath=None):
        diffs = []
        for repo, root in self.repositories:
            if repository and root != repository:
                continue
            #commands.pull(thisui, user_repo)

            # The hg diff command returns the entire set of diffs as one big
            # chunk.  The following code is lifted from the source (version
            # 1.2) as the method for getting the individual diffs.  As such,
            # this is prone to break in the case of internal changes.  We
            # should try and get an external method to do the same thing.
            node1, node2 = cmdutil.revpair(repo, None)

            match = cmdutil.match(repo, (), {})
            repodiffs = []
            for diff in patch.diff(repo, node1, node2, match=match, opts=patch.diffopts(self.ui)):
                diffheader = diff.split('\n')[0]
                filename = DIFF_FILE.match(diffheader).groups()[0]
                if filepath and filepath == filename:
                    return {'repository':root,
                            'filename':filename,
                            'diff': highlight(diff, DiffLexer(), HtmlFormatter())}
                # Should I instantiate a single lexer and formatter and share them?
                repodiffs.append({'repository':root,
                               'filename':filename,
                               'diff': highlight(diff, DiffLexer(), HtmlFormatter())})
            # At the repo level, we want to go through all found files and look
            # for related issues
            try:
                issues = yamltrak.issues([repo.root])[root]
            except KeyError:
                # There is no issue database, or maybe just no open issues...
                issues = {}
            for diff in repodiffs:
                relatedissues = yamltrak.relatedissues(repo.root, filename=diff['filename'], ids=issues.keys())
                related = {}
                for issue in relatedissues:
                    related[issue] = {'repo':root,
                                      'title':issues[issue]['title']}
                diff['relatedissues'] = related
            diffs += repodiffs
        # Done collecting the diffs
        if filepath:
            # User wanted a specific diff, and we didn't find it.  This
            # probably isn't the best exception, but it will have to do...
            raise LookupError

        return diffs
Esempio n. 41
0
def override_forget(orig, ui, repo, *pats, **opts):
    wctx = repo[None].manifest()
    oldmatch = cmdutil.match
    def override_match(repo, pats=[], opts={}, globbed=False, default='relpath'):
        match = oldmatch(repo, pats, opts, globbed, default)
        m = copy.copy(match)
        notbfile = lambda f: not bfutil.is_standin(f) and bfutil.standin(f) not in wctx
        m._files = [f for f in m._files if notbfile(f)]
        m._fmap = set(m._files)
        orig_matchfn = m.matchfn
        m.matchfn = lambda f: orig_matchfn(f) and notbfile(f)
        return m
    cmdutil.match = override_match
    orig(ui, repo, *pats, **opts)
    cmdutil.match = oldmatch

    m = cmdutil.match(repo, pats, opts)
    try:
        repo.bfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.bfstatus = False
    forget = sorted(s[0] + s[1] + s[3] + s[6])
    forget = [f for f in forget if bfutil.standin(f) in wctx]

    for f in forget:
        if bfutil.standin(f) not in repo.dirstate and not os.path.isdir(m.rel(bfutil.standin(f))):
            ui.warn(_('not removing %s: file is already untracked\n')
                    % m.rel(f))

    for f in forget:
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the repository
    # and we could race inbetween.
    wlock = repo.wlock()
    try:
        bfdirstate = bfutil.open_bfdirstate(ui, repo)
        for f in forget:
            bfdirstate.remove(bfutil.unixpath(f))
        bfdirstate.write()
        bfutil.repo_remove(repo, [bfutil.standin(f) for f in forget], unlink=True)
    finally:
        wlock.release()
Esempio n. 42
0
    def pdiff(self, pats, opts, parent=None):
        'Return diffs relative to PARENT, as best as we can make out'

        parent = self.parent(parent)
        act = self.active(parent)

        #
        # act.localtip maybe nil, in the case of uncommitted local
        # changes.
        #
        if not act.revs:
            return

        matchfunc = cmdutil.match(self.repo, pats, opts)
        opts = patch.diffopts(self.ui, opts)

        return self.diff(act.parenttip.node(), act.localtip.node(),
                         match=matchfunc, opts=opts)
Esempio n. 43
0
    def __difftree(repo, node1, node2, files=[]):
        assert node2 is not None
        mmap = repo[node1].manifest()
        mmap2 = repo[node2].manifest()
        m = cmdutil.match(repo, files)
        modified, added, removed  = repo.status(node1, node2, m)[:3]
        empty = short(nullid)

        for f in modified:
            # TODO get file permissions
            ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
                     (short(mmap[f]), short(mmap2[f]), f, f))
        for f in added:
            ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
                     (empty, short(mmap2[f]), f, f))
        for f in removed:
            ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
                     (short(mmap[f]), empty, f, f))
Esempio n. 44
0
    def __difftree(repo, node1, node2, files=[]):
        assert node2 is not None
        mmap = repo[node1].manifest()
        mmap2 = repo[node2].manifest()
        m = cmdutil.match(repo, files)
        modified, added, removed = repo.status(node1, node2, m)[:3]
        empty = short(nullid)

        for f in modified:
            # TODO get file permissions
            ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
                     (short(mmap[f]), short(mmap2[f]), f, f))
        for f in added:
            ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
                     (empty, short(mmap2[f]), f, f))
        for f in removed:
            ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
                     (short(mmap[f]), empty, f, f))
Esempio n. 45
0
def commits(ui, repo, *pats, **opts):
    node1, node2 = cmdutil.revpair(repo, opts.get('rev'))

    matcher = cmdutil.match(repo, pats, opts)
    cwd = (pats and repo.getcwd()) or ''
    modified, added, removed, deleted, unknown, ignored, clean = \
              repo.status(node1=node1, node2=node2,
                          match=matcher,
                          unknown=True)

    changetypes = (('modified', 'M', modified),
                   ('added', 'A', added),
                   ('removed', 'R', removed),
                   ('deleted', '!', deleted),
                   ('unknown', '?', unknown),
                   )

    end = '\n'
    status_lines = [end]
    status_lines.append("%s %s%s" % (_pfx_root, repo.root, end))
    for opt, char, changes in changetypes:
        format = "%s  %s %%s%s" % (_pfx, char, end)
        for f in changes:
            status_lines.append(format % repo.pathto(f, cwd))

    contents = cmdutil.logmessage(opts)
    if not contents:
        contents = ui.edit("".join(status_lines), opts['user'])

    sets = parse_changesets(contents)
    if sets is None:
        sys.exit(1)

    for i, (message, files) in enumerate(sets):
        print 'Committing set %d' % (i+1)
        print message
        for fn in files:
            print fn
        print

        m = match.match(repo.root, '', files, exact=True)
        if not opts['dry_run']:
            repo.commit(match=m, text=message, user=opts['user'], date=opts['date'], force=util.always)
Esempio n. 46
0
def casecheck(ui, repo, *pats, **opts):
    if not repo.local():
        ui.note(_('Only local repositories can be checked'))
        return
    '''check an existing local repository for filename issues (caseguard)'''
    m = cmdutil.match(repo, pats, opts)

    seen = dict()

    for f in repo.walk(m):
        if f in repo.dirstate:
            badname = _wincheck(ui, f, ui.status) or \
                        _charcheck(ui, f, ui.status)
            if f.lower() in seen:
                ui.status(_('%s collides with %s\n') % (f, seen[f.lower()]))
            else:
                seen[f.lower()] = f
                if not badname:
                    ui.note(_('\t[OK] %s\n') % f)
Esempio n. 47
0
    def status(self, path=None):
        "show changed files in the working directory"

        revs = None
        node1, node2 = revpair(self.repo, revs)

        cwd = (path and self.repo.getcwd()) or ''
        copy = {}
        states = 'modified added removed deleted unknown ignored clean'.split()
        show = states

        stat = self.repo.status(node1, node2, match(self.repo, path),
                    'ignored' in show, 'clean' in show, 'unknown' in show,
                    )
        changestates = zip(states, 'MAR!?IC', stat)

        for state, char, files in changestates:
            for f in files:
                yield f, state
Esempio n. 48
0
def casecheck(ui, repo, *pats, **opts):
    if not repo.local():
        ui.note(_('Only local repositories can be checked'))
        return
    '''check an existing local repository for filename issues (caseguard)'''
    m = cmdutil.match(repo, pats, opts)

    seen = dict()

    for f in repo.walk(m):
        if f in repo.dirstate:
            badname = _wincheck(ui, f, ui.status) or \
                        _charcheck(ui, f, ui.status)
            if f.lower() in seen:
                ui.status(_('%s collides with %s\n') % (f, seen[f.lower()]))
            else:
                seen[f.lower()] = f
                if not badname:
                    ui.note(_('\t[OK] %s\n') % f)
Esempio n. 49
0
def get_hg_file(repo, file_name, rev, tmp_file_name, dump_to_file = False):
    """ INTERNAL: read a file from the hg repo.
        If dump_to_file, the data is written into tmp_file_name.
        Otherwise, the data is returned and tmp_file_name is deleted.
    """
    #print "get_hg_file -- ", file_name, rev

    file_name = os.path.join(repo.root, file_name)
    ctx = repo[rev]
    bytes = None
    err = True
    matches = cmdutil.match(repo, (file_name,))
    for abs_ in ctx.walk(matches):
        assert err # Wacky. Why are we looping again?
        # REDFLAG: ripped out decode code. Will I need that on windows?
        file_ptr = None # Hmmmm starting to look like crappy Java code :-(
        in_file = None
        try:
            file_ptr = cmdutil.make_file(repo, tmp_file_name, ctx.node(),
                                         pathname=abs_)
            file_ptr.write(ctx[abs_].data())
            file_ptr.close()
            file_ptr = None
            if not dump_to_file:
                in_file = open(tmp_file_name)
                bytes = in_file.read()
        finally:
            if file_ptr:
                file_ptr.close()
            if in_file:
                in_file.close()
            if not dump_to_file and os.path.exists(tmp_file_name):
                os.remove(tmp_file_name)

        err = False
    if err:
        raise KeyError("File: %s doesn't exist in version: %s" \
                       % (file_name, rev))
    if dump_to_file:
        return "The data was written into: %s" % tmp_file_name

    return bytes
Esempio n. 50
0
def autodiff(ui, repo, *pats, **opts):
    diffopts = patch.diffopts(ui, opts)
    git = opts.get('git', 'no')
    brokenfiles = set()
    losedatafn = None
    if git in ('yes', 'no'):
        diffopts.git = git == 'yes'
        diffopts.upgrade = False
    elif git == 'auto':
        diffopts.git = False
        diffopts.upgrade = True
    elif git == 'warn':
        diffopts.git = False
        diffopts.upgrade = True

        def losedatafn(fn=None, **kwargs):
            brokenfiles.add(fn)
            return True
    elif git == 'abort':
        diffopts.git = False
        diffopts.upgrade = True

        def losedatafn(fn=None, **kwargs):
            raise util.Abort('losing data for %s' % fn)
    else:
        raise util.Abort('--git must be yes, no or auto')

    node1, node2 = cmdutil.revpair(repo, [])
    m = cmdutil.match(repo, pats, opts)
    it = patch.diff(repo,
                    node1,
                    node2,
                    match=m,
                    opts=diffopts,
                    losedatafn=losedatafn)
    for chunk in it:
        ui.write(chunk)
    for fn in sorted(brokenfiles):
        ui.write('data lost for: %s\n' % fn)
Esempio n. 51
0
    def matcher(self, pats=None, opts=None, files=None):
        '''Return a match object suitable for Mercurial based on
        specified criteria.

        If files is specified it is a list of pathnames relative to
        the repository root to be matched precisely.

        If pats and/or opts are specified, these are as to
        cmdutil.match'''

        of_patterns = pats is not None or opts is not None
        of_files = files is not None
        opts = opts or {}  # must be a dict

        assert not (of_patterns and of_files)

        if of_patterns:
            return cmdutil.match(self.repo, pats, opts)
        elif of_files:
            return cmdutil.matchfiles(self.repo, files)
        else:
            return cmdutil.matchall(self.repo)
Esempio n. 52
0
    def status(self, path=None):
        "show changed files in the working directory"

        revs = None
        node1, node2 = revpair(self.repo, revs)

        cwd = (path and self.repo.getcwd()) or ''
        copy = {}
        states = 'modified added removed deleted unknown ignored clean'.split()
        show = states

        stat = self.repo.status(
            node1,
            node2,
            match(self.repo, path),
            'ignored' in show,
            'clean' in show,
            'unknown' in show,
        )
        changestates = zip(states, 'MAR!?IC', stat)

        for state, char, files in changestates:
            for f in files:
                yield f, state
Esempio n. 53
0
def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
    '''Do the actuall diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get('rev')
    change = opts.get('change')

    if revs and change:
        msg = _('cannot specify --rev and --change at the same time')
        raise util.Abort(msg)
    elif change:
        node2 = repo.lookup(change)
        node1 = repo[node2].parents()[0].node()
    else:
        node1, node2 = cmdutil.revpair(repo, revs)

    matcher = cmdutil.match(repo, pats, opts)
    modified, added, removed = repo.status(node1, node2, matcher)[:3]
    if not (modified or added or removed):
        return 0

    tmproot = tempfile.mkdtemp(prefix='extdiff.')
    dir2root = ''
    try:
        # Always make a copy of node1
        dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0]
        changes = len(modified) + len(removed) + len(added)

        # If node2 in not the wc or there is >1 change, copy it
        if node2 or changes > 1:
            dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2,
                                           tmproot)
        else:
            # This lets the diff tool open the changed file directly
            dir2 = ''
            dir2root = repo.root
            fns_and_mtime = []

        # If only one change, diff the files instead of the directories
        if changes == 1:
            if len(modified):
                dir1 = os.path.join(dir1, util.localpath(modified[0]))
                dir2 = os.path.join(dir2root, dir2,
                                    util.localpath(modified[0]))
            elif len(removed):
                dir1 = os.path.join(dir1, util.localpath(removed[0]))
                dir2 = os.devnull
            else:
                dir1 = os.devnull
                dir2 = os.path.join(dir2root, dir2, util.localpath(added[0]))

        cmdline = ('%s %s %s %s' %
                   (util.shellquote(diffcmd), ' '.join(diffopts),
                    util.shellquote(dir1), util.shellquote(dir2)))
        ui.debug(_('running %r in %s\n') % (cmdline, tmproot))
        util.system(cmdline, cwd=tmproot)

        for copy_fn, working_fn, mtime in fns_and_mtime:
            if os.path.getmtime(copy_fn) != mtime:
                ui.debug(
                    _('file changed while diffing. '
                      'Overwriting: %s (src: %s)\n') % (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_('cleaning up temp directory\n'))
        shutil.rmtree(tmproot)
Esempio n. 54
0
def rdiff(ui, repo, url, lrev=None, rrev=None, *pats, **opts):
    def rui():
        try:
            return hg.remoteui(repo, opts)
        except AttributeError:
            # pre 1.6
            return cmdutil.remoteui(repo, opts)

    try:
        other = getpeer(rui(), {}, url)
    except AttributeError:
        # pre-1.3
        other = hg.repository(ui, url)
        cmdutil.setremoteconfig(ui, opts)
    ui.status(_('comparing with %s\n') % url)

    if rrev:
        if capable(other, 'lookup'):
            rrev = other.lookup(rrev)
        else:
            error = _(
                "Other repository doesn't support revision lookup, so a rev cannot be specified."
            )
            raise util.Abort(error)

    incoming = findincomingfn(repo)(other, heads=rrev and [rrev] or [])
    if not incoming:
        # remote is a subset of local
        if not rrev:
            if capable(other, 'lookup'):
                rrev = other.lookup('tip')
            else:
                raise util.Abort(_('cannot determine remote tip'))
        other = repo

    bundle = None
    try:
        if incoming:
            # create a bundle (uncompressed if other repo is not local)
            if not rrev:
                cg = other.changegroup(incoming, "incoming")
            else:
                if not capable(other, 'changegroupsubset'):
                    raise util.Abort(
                        _("Partial incoming cannot be done because other repository doesn't support changegroupsubset."
                          ))
                cg = other.changegroupsubset(incoming, rrev and [rrev] or [],
                                             'incoming')
            bundle = changegroup.writebundle(cg, '', 'HG10UN')
            other = hg.repository(ui, bundle)

        if lrev:
            lrev = repo.changectx(lrev).node()

        rrev = other.changectx(rrev or 'tip').node()
        if opts['reverse']:
            lrev, rrev = rrev, lrev
        if not lrev:
            # bundle dirstate removed prior to hg 1.1
            lrev = repo.dirstate.parents()[0]

        try:
            try:
                # scmutil.match expects a context not a repo
                m = scmutil.match(repo[None], pats, opts)
            except (ImportError, AttributeError):
                m = cmdutil.match(repo, pats, opts)
            chunks = patch.diff(other,
                                lrev,
                                rrev,
                                match=m,
                                opts=patch.diffopts(ui, opts))
            for chunk in chunks:
                ui.write(chunk)
        except AttributeError:
            # 1.0 compatibility
            fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
            patch.diff(other,
                       lrev,
                       rrev,
                       fns,
                       match=matchfn,
                       opts=patch.diffopts(ui, opts))

    finally:
        if hasattr(other, 'close'):
            other.close()
        if bundle:
            os.unlink(bundle)
Esempio n. 55
0
def purge(ui, repo, *dirs, **opts):
    '''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.
    '''
    act = not opts['print']
    eol = '\n'
    if opts['print0']:
        eol = '\0'
        act = False # --print0 implies --print

    def remove(remove_func, name):
        if act:
            try:
                remove_func(repo.wjoin(name))
            except OSError:
                m = _('%s cannot be removed') % name
                if opts['abort_on_err']:
                    raise util.Abort(m)
                ui.warn(_('warning: %s\n') % m)
        else:
            ui.write('%s%s' % (name, eol))

    def removefile(path):
        try:
            os.remove(path)
        except OSError:
            # read-only files cannot be unlinked under Windows
            s = os.stat(path)
            if (s.st_mode & stat.S_IWRITE) != 0:
                raise
            os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
            os.remove(path)

    directories = []
    match = cmdutil.match(repo, dirs, opts)
    match.dir = directories.append
    status = repo.status(match=match, ignored=opts['all'], unknown=True)

    for f in sorted(status[4] + status[5]):
        ui.note(_('Removing file %s\n') % f)
        remove(removefile, f)

    for f in sorted(directories, reverse=True):
        if match(f) and not os.listdir(repo.wjoin(f)):
            ui.note(_('Removing directory %s\n') % f)
            remove(os.rmdir, f)
Esempio n. 56
0
def impl_hg_node(repo, cid, path, *args):
    m = cmdutil.match(repo, pats=[path], default=path)
    rev_iter = cmdutil.walkchangerevs(repo, m, {'rev': cid}, lambda c, f: None)
    return rev_iter.next().hex()
Esempio n. 57
0
 def haschanges(self, repo, pats=[], opts={}):
     """checks if repository has changes or not"""
     return list(
         patch.diff(repo,
                    match=cmdutil.match(repo, pats, opts),
                    opts=self.diffopts(opts))) != []
Esempio n. 58
0
def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
    '''Do the actuall diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get('rev')
    change = opts.get('change')
    args = ' '.join(diffopts)
    do3way = '$parent2' in args

    if revs and change:
        msg = _('cannot specify --rev and --change at the same time')
        raise util.Abort(msg)
    elif change:
        node2 = repo.lookup(change)
        node1a, node1b = repo.changelog.parents(node2)
    else:
        node1a, node2 = cmdutil.revpair(repo, revs)
        if not revs:
            node1b = repo.dirstate.parents()[1]
        else:
            node1b = nullid

    # Disable 3-way merge if there is only one parent
    if do3way:
        if node1b == nullid:
            do3way = False

    matcher = cmdutil.match(repo, pats, opts)
    mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
    if do3way:
        mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
    else:
        mod_b, add_b, rem_b = set(), set(), set()
    modadd = mod_a | add_a | mod_b | add_b
    common = modadd | rem_a | rem_b
    if not common:
        return 0

    tmproot = tempfile.mkdtemp(prefix='extdiff.')
    try:
        # Always make a copy of node1a (and node1b, if applicable)
        dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
        dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
        if do3way:
            dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
            dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
        else:
            dir1b = None

        fns_and_mtime = []

        # If node2 in not the wc or there is >1 change, copy it
        dir2root = ''
        if node2:
            dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
        elif len(common) > 1:
            #we only actually need to get the files to copy back to
            #the working dir in this case (because the other cases
            #are: diffing 2 revisions or single file -- in which case
            #the file is already directly passed to the diff tool).
            dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
        else:
            # This lets the diff tool open the changed file directly
            dir2 = ''
            dir2root = repo.root

        # If only one change, diff the files instead of the directories
        # Handle bogus modifies correctly by checking if the files exist
        if len(common) == 1:
            common_file = util.localpath(common.pop())
            dir1a = os.path.join(dir1a, common_file)
            if not os.path.isfile(os.path.join(tmproot, dir1a)):
                dir1a = os.devnull
            if do3way:
                dir1b = os.path.join(dir1b, common_file)
                if not os.path.isfile(os.path.join(tmproot, dir1b)):
                    dir1b = os.devnull
            dir2 = os.path.join(dir2root, dir2, common_file)

        # Function to quote file/dir names in the argument string.
        # When not operating in 3-way mode, an empty string is
        # returned for parent2
        replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b, child=dir2)

        def quote(match):
            key = match.group()[1:]
            if not do3way and key == 'parent2':
                return ''
            return util.shellquote(replace[key])

        # Match parent2 first, so 'parent1?' will match both parent1 and parent
        regex = '\$(parent2|parent1?|child)'
        if not do3way and not re.search(regex, args):
            args += ' $parent1 $child'
        args = re.sub(regex, quote, args)
        cmdline = util.shellquote(diffcmd) + ' ' + args

        ui.debug('running %r in %s\n' % (cmdline, tmproot))
        util.system(cmdline, cwd=tmproot)

        for copy_fn, working_fn, mtime in fns_and_mtime:
            if os.path.getmtime(copy_fn) != mtime:
                ui.debug('file changed while diffing. '
                         'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_('cleaning up temp directory\n'))
        shutil.rmtree(tmproot)