Example #1
0
def commitextra(ui, repo, *pats, **opts):
    '''make a commit with extra fields'''
    fields = opts.get('field')
    extras = {}
    for field in fields:
        k, v = field.split(b'=', 1)
        extras[k] = v
    message = cmdutil.logmessage(ui, pycompat.byteskwargs(opts))
    repo.commit(message, opts.get('user'), opts.get('date'),
                match=scmutil.match(repo[None], pats,
                                    pycompat.byteskwargs(opts)),
                extra=extras)
    return 0
def _getpatchmsgs(repo, sender, revs, patchnames=None, **opts):
    """return a list of emails from a list of patches

    This involves introduction message creation if necessary.

    This function returns a list of "email" tuples (subject, content, None).
    """
    bytesopts = pycompat.byteskwargs(opts)
    ui = repo.ui
    _charsets = mail._charsets(ui)
    patches = list(_getpatches(repo, revs, **opts))
    msgs = []

    ui.write(_('this patch series consists of %d patches.\n\n') % len(patches))

    # build the intro message, or skip it if the user declines
    if introwanted(ui, bytesopts, len(patches)):
        msg = _makeintro(repo, sender, revs, patches, **opts)
        if msg:
            msgs.append(msg)

    # are we going to send more than one message?
    numbered = len(msgs) + len(patches) > 1

    # now generate the actual patch messages
    name = None
    assert len(revs) == len(patches)
    for i, (r, p) in enumerate(zip(revs, patches)):
        if patchnames:
            name = patchnames[i]
        msg = makepatch(ui, repo, r, p, bytesopts, _charsets, i + 1,
                        len(patches), numbered, name)
        msgs.append(msg)

    return msgs
Example #3
0
def log(orig, ui, repo, *pats, **opts):
    if not isenabled(repo):
        return orig(ui, repo, *pats, **opts)

    follow = opts.get('follow')
    revs = opts.get('rev')
    if pats:
        # Force slowpath for non-follow patterns and follows that start from
        # non-working-copy-parent revs.
        if not follow or revs:
            # This forces the slowpath
            opts['removed'] = True

        # If this is a non-follow log without any revs specified, recommend that
        # the user add -f to speed it up.
        if not follow and not revs:
            match = scmutil.match(repo[b'.'], pats, pycompat.byteskwargs(opts))
            isfile = not match.anypats()
            if isfile:
                for file in match.files():
                    if not os.path.isfile(repo.wjoin(file)):
                        isfile = False
                        break

            if isfile:
                ui.warn(
                    _(b"warning: file log can be slow on large repos - " +
                      b"use -f to speed it up\n"))

    return orig(ui, repo, *pats, **opts)
def extdiff(ui, repo, *pats, **opts):
    '''use external program to diff repository (or selected files)

    Show differences between revisions for the specified files, using
    an external program. The default program used is diff, with
    default options "-Npru".

    To select a different program, use the -p/--program option. The
    program will be passed the names of two directories to compare. To
    pass additional options to the program, use -o/--option. These
    will be passed before the names of the directories to compare.

    When two revision arguments are given, then changes are shown
    between those revisions. If only one revision is specified then
    that revision is compared to the working directory, and, when no
    revisions are specified, the working directory files are compared
    to its parent.'''
    opts = pycompat.byteskwargs(opts)
    program = opts.get('program')
    option = opts.get('option')
    if not program:
        program = 'diff'
        option = option or ['-Npru']
    cmdline = ' '.join(map(util.shellquote, [program] + option))
    return dodiff(ui, repo, cmdline, pats, opts)
Example #5
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 the following by default:

    - 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`)

    The --files and --dirs options can be used to direct purge to delete
    only files, only directories, or both. If neither option is given,
    both will be deleted.

    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.
    '''
    opts = pycompat.byteskwargs(opts)

    act = not opts.get(b'print')
    eol = b'\n'
    if opts.get(b'print0'):
        eol = b'\0'
        act = False  # --print0 implies --print

    removefiles = opts.get(b'files')
    removedirs = opts.get(b'dirs')

    if not removefiles and not removedirs:
        removefiles = True
        removedirs = True

    match = scmutil.match(repo[None], dirs, opts)

    paths = mergemod.purge(
        repo,
        match,
        ignored=opts.get(b'all', False),
        removeemptydirs=removedirs,
        removefiles=removefiles,
        abortonerror=opts.get(b'abort_on_err'),
        noop=not act,
    )

    for path in paths:
        if not act:
            ui.write(b'%s%s' % (path, eol))
def children(ui, repo, file_=None, **opts):
    """show the children of the given or working directory revision

    Print the children of the working directory's revisions. If a
    revision is given via -r/--rev, the children of that revision will
    be printed. If a file argument is given, revision in which the
    file was last changed (after the working directory revision or the
    argument to --rev if given) is printed.

    Please use :hg:`log` instead::

        hg children => hg log -r "children(.)"
        hg children -r REV => hg log -r "children(REV)"

    See :hg:`help log` and :hg:`help revsets.children`.

    """
    opts = pycompat.byteskwargs(opts)
    rev = opts.get('rev')
    if file_:
        fctx = repo.filectx(file_, changeid=rev)
        childctxs = [fcctx.changectx() for fcctx in fctx.children()]
    else:
        ctx = repo[rev]
        childctxs = ctx.children()

    displayer = cmdutil.show_changeset(ui, repo, opts)
    for cctx in childctxs:
        displayer.show(cctx)
    displayer.close()
Example #7
0
def extdiff2(ui, repo, *pats, **opts):
  """use external program to diff repository (or selected files)

    Show differences between revisions for the specified files, using
    an external program. The default program used is diff, with
    default options "-Npru".

    To select a different program, use the -p/--program option. The
    program will be passed the names of two directories to compare. To
    pass additional options to the program, use -o/--option. These
    will be passed before the names of the directories to compare.

    When two revision arguments are given, then changes are shown
    between those revisions. If only one revision is specified then
    that revision is compared to the working directory, and, when no
    revisions are specified, the working directory files are compared
    to its parent.
  """
  opts = pycompat.byteskwargs(opts)
  program = opts.get('program')
  option = opts.get('option')
  if not program:
    program = 'diff'
    option = option or ['-Npru']
  cmdline = ' '.join(map(procutil.shellquote, [program] + option))
  return dodiff(ui, repo, cmdline, pats, opts)
Example #8
0
def phabupdate(ui, repo, spec, **opts):
    """update Differential Revision in batch

    DREVSPEC selects revisions. See :hg:`help phabread` for its usage.
    """
    opts = pycompat.byteskwargs(opts)
    flags = [
        n for n in b'accept reject abandon reclaim'.split() if opts.get(n)
    ]
    if len(flags) > 1:
        raise error.Abort(_(b'%s cannot be used together') % b', '.join(flags))

    actions = []
    for f in flags:
        actions.append({b'type': f, b'value': b'true'})

    drevs = querydrev(repo, spec)
    for i, drev in enumerate(drevs):
        if i + 1 == len(drevs) and opts.get(b'comment'):
            actions.append({b'type': b'comment', b'value': opts[b'comment']})
        if actions:
            params = {
                b'objectIdentifier': drev[b'phid'],
                b'transactions': actions
            }
            callconduit(ui, b'differential.revision.edit', params)
Example #9
0
def absorbcmd(ui, repo, *pats, **opts):
    """incorporate corrections into the stack of draft changesets

    absorb analyzes each change in your working directory and attempts to
    amend the changed lines into the changesets in your stack that first
    introduced those lines.

    If absorb cannot find an unambiguous changeset to amend for a change,
    that change will be left in the working directory, untouched. They can be
    observed by :hg:`status` or :hg:`diff` afterwards. In other words,
    absorb does not write to the working directory.

    Changesets outside the revset `::. and not public() and not merge()` will
    not be changed.

    Changesets that become empty after applying the changes will be deleted.

    By default, absorb will show what it plans to do and prompt for
    confirmation.  If you are confident that the changes will be absorbed
    to the correct place, run :hg:`absorb -a` to apply the changes
    immediately.

    Returns 0 on success, 1 if all chunks were ignored and nothing amended.
    """
    opts = pycompat.byteskwargs(opts)

    with repo.wlock(), repo.lock():
        if not opts[b'dry_run']:
            cmdutil.checkunfinished(repo)

        state = absorb(ui, repo, pats=pats, opts=opts)
        if sum(s[0] for s in state.chunkstats.values()) == 0:
            return 1
Example #10
0
 def __call__(self, ui, repo, *pats, **opts):
     opts = pycompat.byteskwargs(opts)
     options = b' '.join(map(procutil.shellquote, opts[b'option']))
     if options:
         options = b' ' + options
     return dodiff(
         ui, repo, self._cmdline + options, pats, opts, guitool=self._isgui
     )
Example #11
0
def fix(ui, repo, *pats, **opts):
    """rewrite file content in changesets or working directory

    Runs any configured tools to fix the content of files. Only affects files
    with changes, unless file arguments are provided. Only affects changed lines
    of files, unless the --whole flag is used. Some tools may always affect the
    whole file regardless of --whole.

    If revisions are specified with --rev, those revisions will be checked, and
    they may be replaced with new revisions that have fixed file content.  It is
    desirable to specify all descendants of each specified revision, so that the
    fixes propagate to the descendants. If all descendants are fixed at the same
    time, no merging, rebasing, or evolution will be required.

    If --working-dir is used, files with uncommitted changes in the working copy
    will be fixed. If the checked-out revision is also fixed, the working
    directory will update to the replacement revision.

    When determining what lines of each file to fix at each revision, the whole
    set of revisions being fixed is considered, so that fixes to earlier
    revisions are not forgotten in later ones. The --base flag can be used to
    override this default behavior, though it is not usually desirable to do so.
    """
    opts = pycompat.byteskwargs(opts)
    if opts['all']:
        if opts['rev']:
            raise error.Abort(_('cannot specify both "--rev" and "--all"'))
        opts['rev'] = ['not public() and not obsolete()']
        opts['working_dir'] = True
    with repo.wlock(), repo.lock():
        revstofix = getrevstofix(ui, repo, opts)
        basectxs = getbasectxs(repo, opts, revstofix)
        workqueue, numitems = getworkqueue(ui, repo, pats, opts, revstofix,
                                           basectxs)
        filedata = collections.defaultdict(dict)
        replacements = {}
        fixers = getfixers(ui)
        # Some day this loop can become a worker pool, but for now it's easier
        # to fix everything serially in topological order.
        for rev, path in sorted(workqueue):
            ctx = repo[rev]
            olddata = ctx[path].data()
            newdata = fixfile(ui, opts, fixers, ctx, path, basectxs[rev])
            if newdata != olddata:
                filedata[rev][path] = newdata
            numitems[rev] -= 1
            if not numitems[rev]:
                if rev == wdirrev:
                    writeworkingdir(repo, ctx, filedata[rev], replacements)
                else:
                    replacerev(ui, repo, ctx, filedata[rev], replacements)
                del filedata[rev]

        replacements = {
            prec: [succ]
            for prec, succ in replacements.iteritems()
        }
        scmutil.cleanupnodes(repo, replacements, 'fix')
Example #12
0
def countrate(ui, repo, amap, *pats, **opts):
    """Calculate stats"""
    opts = pycompat.byteskwargs(opts)
    if opts.get(b'dateformat'):

        def getkey(ctx):
            t, tz = ctx.date()
            date = datetime.datetime(*time.gmtime(float(t) - tz)[:6])
            return encoding.strtolocal(
                date.strftime(encoding.strfromlocal(opts[b'dateformat']))
            )

    else:
        tmpl = opts.get(b'oldtemplate') or opts.get(b'template')
        tmpl = logcmdutil.maketemplater(ui, repo, tmpl)

        def getkey(ctx):
            ui.pushbuffer()
            tmpl.show(ctx)
            return ui.popbuffer()

    progress = ui.makeprogress(
        _(b'analyzing'), unit=_(b'revisions'), total=len(repo)
    )
    rate = {}
    df = False
    if opts.get(b'date'):
        df = dateutil.matchdate(opts[b'date'])

    m = scmutil.match(repo[None], 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).strip()
        key = amap.get(key, key)  # alias remap
        if opts.get(b'changesets'):
            rate[key] = (rate.get(key, (0,))[0] + 1, 0)
        else:
            parents = ctx.parents()
            if len(parents) > 1:
                ui.note(_(b'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)]

        progress.increment()

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

    progress.complete()

    return rate
Example #13
0
def files(ui, repo, *pats, **opts):
    '''show files configured for keyword expansion

    List which files in the working directory are matched by the
    [keyword] configuration patterns.

    Useful to prevent inadvertent keyword expansion and to speed up
    execution by including only files that are actual candidates for
    expansion.

    See :hg:`help keyword` on how to construct patterns both for
    inclusion and exclusion of files.

    With -A/--all and -v/--verbose the codes used to show the status
    of files are::

      K = keyword expansion candidate
      k = keyword expansion candidate (not tracked)
      I = ignored
      i = ignored (not tracked)
    '''
    kwt = getattr(repo, '_keywordkwt', None)
    wctx = repo[None]
    status = _status(ui, repo, wctx, kwt, *pats, **opts)
    if pats:
        cwd = repo.getcwd()
    else:
        cwd = ''
    files = []
    opts = pycompat.byteskwargs(opts)
    if not opts.get('unknown') or opts.get('all'):
        files = sorted(status.modified + status.added + status.clean)
    kwfiles = kwt.iskwfile(files, wctx)
    kwdeleted = kwt.iskwfile(status.deleted, wctx)
    kwunknown = kwt.iskwfile(status.unknown, wctx)
    if not opts.get('ignore') or opts.get('all'):
        showfiles = kwfiles, kwdeleted, kwunknown
    else:
        showfiles = [], [], []
    if opts.get('all') or opts.get('ignore'):
        showfiles += ([f for f in files if f not in kwfiles],
                      [f for f in status.unknown if f not in kwunknown])
    kwlabels = 'enabled deleted enabledunknown ignored ignoredunknown'.split()
    kwstates = zip(kwlabels, 'K!kIi', showfiles)
    fm = ui.formatter('kwfiles', opts)
    fmt = '%.0s%s\n'
    if opts.get('all') or ui.verbose:
        fmt = '%s %s\n'
    for kwstate, char, filenames in kwstates:
        label = 'kwfiles.' + kwstate
        for f in filenames:
            fm.startitem()
            fm.write('kwstatus path',
                     fmt,
                     char,
                     repo.pathto(f, cwd),
                     label=label)
    fm.end()
def changesetentry(orig, web, ctx):
    """Wraps webutil.changesetentry to provide extra metadata."""
    d = orig(web, ctx)

    d = pycompat.byteskwargs(d)

    addmetadata(web.repo, ctx, d)

    return pycompat.strkwargs(d)
Example #15
0
 def _call(self, cmd, **args):
     args = pycompat.byteskwargs(args)
     res = wireprotov1server.dispatch(self.serverrepo, proto(args), cmd)
     if isinstance(res, wireprototypes.bytesresponse):
         return res.data
     elif isinstance(res, bytes):
         return res
     else:
         raise error.Abort('dummy client does not support response type')
Example #16
0
def _pull(orig, ui, repo, source="default", **opts):
    opts = pycompat.byteskwargs(opts)
    # Copy paste from `pull` command
    source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))

    scratchbookmarks = {}
    unfi = repo.unfiltered()
    unknownnodes = []
    for rev in opts.get('rev', []):
        if rev not in unfi:
            unknownnodes.append(rev)
    if opts.get('bookmark'):
        bookmarks = []
        revs = opts.get('rev') or []
        for bookmark in opts.get('bookmark'):
            if _scratchbranchmatcher(bookmark):
                # rev is not known yet
                # it will be fetched with listkeyspatterns next
                scratchbookmarks[bookmark] = 'REVTOFETCH'
            else:
                bookmarks.append(bookmark)

        if scratchbookmarks:
            other = hg.peer(repo, opts, source)
            fetchedbookmarks = other.listkeyspatterns(
                'bookmarks', patterns=scratchbookmarks)
            for bookmark in scratchbookmarks:
                if bookmark not in fetchedbookmarks:
                    raise error.Abort('remote bookmark %s not found!' %
                                      bookmark)
                scratchbookmarks[bookmark] = fetchedbookmarks[bookmark]
                revs.append(fetchedbookmarks[bookmark])
        opts['bookmark'] = bookmarks
        opts['rev'] = revs

    if scratchbookmarks or unknownnodes:
        # Set anyincoming to True
        extensions.wrapfunction(discovery, 'findcommonincoming',
                                _findcommonincoming)
    try:
        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before pull and restore after
        remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, source)
        result = orig(ui, repo, source, **pycompat.strkwargs(opts))
        # TODO(stash): race condition is possible
        # if scratch bookmarks was updated right after orig.
        # But that's unlikely and shouldn't be harmful.
        if common.isremotebooksenabled(ui):
            remotescratchbookmarks.update(scratchbookmarks)
            _saveremotebookmarks(repo, remotescratchbookmarks, source)
        else:
            _savelocalbookmarks(repo, scratchbookmarks)
        return result
    finally:
        if scratchbookmarks:
            extensions.unwrapfunction(discovery, 'findcommonincoming')
Example #17
0
def _status(ui, repo, wctx, kwt, *pats, **opts):
    '''Bails out if [keyword] configuration is not active.
    Returns status of working directory.'''
    if kwt:
        opts = pycompat.byteskwargs(opts)
        return repo.status(match=scmutil.match(wctx, pats, opts), clean=True,
                           unknown=opts.get('unknown') or opts.get('all'))
    if ui.configitems('keyword'):
        raise error.Abort(_('[keyword] patterns cannot match'))
    raise error.Abort(_('no [keyword] patterns configured'))
Example #18
0
def view(ui, repo, *etc, **opts):
    "start interactive history viewer"
    opts = pycompat.byteskwargs(opts)
    os.chdir(repo.root)
    optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v])
    if repo.filtername is None:
        optstr += '--hidden'

    cmd = ui.config("hgk", "path") + " %s %s" % (optstr, " ".join(etc))
    ui.debug("running %s\n" % cmd)
    ui.system(cmd, blockedtag='hgk_view')
def _push(orig, ui, repo, *dests, **opts):
    opts = pycompat.byteskwargs(opts)
    bookmark = opts.get(b'bookmark')
    # we only support pushing one infinitepush bookmark at once
    if len(bookmark) == 1:
        bookmark = bookmark[0]
    else:
        bookmark = b''

    oldphasemove = None
    overrides = {(experimental, configbookmark): bookmark}

    with ui.configoverride(overrides, b'infinitepush'):
        scratchpush = opts.get(b'bundle_store')
        if _scratchbranchmatcher(bookmark):
            scratchpush = True
            # bundle2 can be sent back after push (for example, bundle2
            # containing `pushkey` part to update bookmarks)
            ui.setconfig(experimental, b'bundle2.pushback', True)

        if scratchpush:
            # this is an infinitepush, we don't want the bookmark to be applied
            # rather that should be stored in the bundlestore
            opts[b'bookmark'] = []
            ui.setconfig(experimental, configscratchpush, True)
            oldphasemove = extensions.wrapfunction(
                exchange, b'_localphasemove', _phasemove
            )

        paths = list(urlutil.get_push_paths(repo, ui, dests))
        if len(paths) > 1:
            msg = _(b'cannot push to multiple path with infinitepush')
            raise error.Abort(msg)

        path = paths[0]
        destpath = path.pushloc or path.loc
        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before push and restore after
        remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, destpath)
        result = orig(ui, repo, *dests, **pycompat.strkwargs(opts))
        if common.isremotebooksenabled(ui):
            if bookmark and scratchpush:
                other = hg.peer(repo, opts, destpath)
                try:
                    fetchedbookmarks = other.listkeyspatterns(
                        b'bookmarks', patterns=[bookmark]
                    )
                    remotescratchbookmarks.update(fetchedbookmarks)
                finally:
                    other.close()
            _saveremotebookmarks(repo, remotescratchbookmarks, destpath)
    if oldphasemove:
        exchange._localphasemove = oldphasemove
    return result
Example #20
0
def close_branch(ui, repo, *revs, **opts):
    """close the given head revisions

    This is equivalent to checking out each revision in a clean tree and running
    ``hg commit --close-branch``, except that it doesn't change the working
    directory.

    The commit message must be specified with -l or -m.
    """
    def docommit(rev):
        cctx = context.memctx(
            repo,
            parents=[rev, None],
            text=message,
            files=[],
            filectxfn=None,
            user=opts.get(b'user'),
            date=opts.get(b'date'),
            extra=extra,
        )
        tr = repo.transaction(b'commit')
        ret = repo.commitctx(cctx, True)
        bookmarks.update(repo, [rev, None], ret)
        cctx.markcommitted(ret)
        tr.close()

    opts = pycompat.byteskwargs(opts)

    revs += tuple(opts.get(b'rev', []))
    revs = scmutil.revrange(repo, revs)

    if not revs:
        raise error.Abort(_(b'no revisions specified'))

    heads = []
    for branch in repo.branchmap():
        heads.extend(repo.branchheads(branch))
    heads = {repo[h].rev() for h in heads}
    for rev in revs:
        if rev not in heads:
            raise error.Abort(_(b'revision is not an open head: %d') % rev)

    message = cmdutil.logmessage(ui, opts)
    if not message:
        raise error.Abort(_(b"no commit message specified with -l or -m"))
    extra = {b'close': b'1'}

    with repo.wlock(), repo.lock():
        for rev in revs:
            r = repo[rev]
            branch = r.branch()
            extra[b'branch'] = branch
            docommit(r)
    return 0
Example #21
0
def convert(ui, src, dest=None, revmapfile=None, **opts):
    opts = pycompat.byteskwargs(opts)
    global orig_encoding
    orig_encoding = encoding.encoding
    encoding.encoding = b'UTF-8'

    # support --authors as an alias for --authormap
    if not opts.get(b'authormap'):
        opts[b'authormap'] = opts.get(b'authors')

    if not dest:
        dest = hg.defaultdest(src) + b"-hg"
        ui.status(_(b"assuming destination %s\n") % dest)

    destc = convertsink(ui, dest, opts.get(b'dest_type'))
    destc = scmutil.wrapconvertsink(destc)

    try:
        srcc, defaultsort = convertsource(
            ui, src, opts.get(b'source_type'), opts.get(b'rev')
        )
    except Exception:
        for path in destc.created:
            shutil.rmtree(path, True)
        raise

    sortmodes = (b'branchsort', b'datesort', b'sourcesort', b'closesort')
    sortmode = [m for m in sortmodes if opts.get(m)]
    if len(sortmode) > 1:
        raise error.Abort(_(b'more than one sort mode specified'))
    if sortmode:
        sortmode = sortmode[0]
    else:
        sortmode = defaultsort

    if sortmode == b'sourcesort' and not srcc.hasnativeorder():
        raise error.Abort(
            _(b'--sourcesort is not supported by this data source')
        )
    if sortmode == b'closesort' and not srcc.hasnativeclose():
        raise error.Abort(
            _(b'--closesort is not supported by this data source')
        )

    fmap = opts.get(b'filemap')
    if fmap:
        srcc = filemap.filemap_source(ui, srcc, fmap)
        destc.setfilemapmode(True)

    if not revmapfile:
        revmapfile = destc.revmapfile()

    c = converter(ui, srcc, destc, revmapfile, opts)
    c.convert(sortmode)
Example #22
0
def debugbuildannotatecache(ui, repo, *pats, **opts):
    """incrementally build fastannotate cache up to REV for specified files

    If REV is not specified, use the config 'fastannotate.mainbranch'.

    If fastannotate.client is True, download the annotate cache from the
    server. Otherwise, build the annotate cache locally.

    The annotate cache will be built using the default diff and follow
    options and lives in '.hg/fastannotate/default'.
    """
    opts = pycompat.byteskwargs(opts)
    rev = opts.get(b'REV') or ui.config(b'fastannotate', b'mainbranch')
    if not rev:
        raise error.Abort(
            _(b'you need to provide a revision'),
            hint=_(b'set fastannotate.mainbranch or use --rev'),
        )
    if ui.configbool(b'fastannotate', b'unfilteredrepo'):
        repo = repo.unfiltered()
    ctx = scmutil.revsingle(repo, rev)
    m = scmutil.match(ctx, pats, opts)
    paths = list(ctx.walk(m))
    if util.safehasattr(repo, 'prefetchfastannotate'):
        # client
        if opts.get(b'REV'):
            raise error.Abort(_(b'--rev cannot be used for client'))
        repo.prefetchfastannotate(paths)
    else:
        # server, or full repo
        progress = ui.makeprogress(_(b'building'), total=len(paths))
        for i, path in enumerate(paths):
            progress.update(i)
            with facontext.annotatecontext(repo, path) as actx:
                try:
                    if actx.isuptodate(rev):
                        continue
                    actx.annotate(rev, rev)
                except (faerror.CannotReuseError, faerror.CorruptedFileError):
                    # the cache is broken (could happen with renaming so the
                    # file history gets invalidated). rebuild and try again.
                    ui.debug(b'fastannotate: %s: rebuilding broken cache\n' %
                             path)
                    actx.rebuild()
                    try:
                        actx.annotate(rev, rev)
                    except Exception as ex:
                        # possibly a bug, but should not stop us from building
                        # cache for other files.
                        ui.warn(
                            _(b'fastannotate: %s: failed to '
                              b'build cache: %r\n') % (path, ex))
        progress.complete()
Example #23
0
def _push(orig, ui, repo, dest=None, *args, **opts):
    opts = pycompat.byteskwargs(opts)
    bookmark = opts.get(b'bookmark')
    # we only support pushing one infinitepush bookmark at once
    if len(bookmark) == 1:
        bookmark = bookmark[0]
    else:
        bookmark = b''

    oldphasemove = None
    overrides = {(experimental, configbookmark): bookmark}

    with ui.configoverride(overrides, b'infinitepush'):
        scratchpush = opts.get(b'bundle_store')
        if _scratchbranchmatcher(bookmark):
            scratchpush = True
            # bundle2 can be sent back after push (for example, bundle2
            # containing `pushkey` part to update bookmarks)
            ui.setconfig(experimental, b'bundle2.pushback', True)

        if scratchpush:
            # this is an infinitepush, we don't want the bookmark to be applied
            # rather that should be stored in the bundlestore
            opts[b'bookmark'] = []
            ui.setconfig(experimental, configscratchpush, True)
            oldphasemove = extensions.wrapfunction(exchange,
                                                   b'_localphasemove',
                                                   _phasemove)
        # Copy-paste from `push` command
        path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
        if not path:
            raise error.Abort(
                _(b'default repository not configured!'),
                hint=_(b"see 'hg help config.paths'"),
            )
        destpath = path.pushloc or path.loc
        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before push and restore after
        remotescratchbookmarks = _readscratchremotebookmarks(
            ui, repo, destpath)
        result = orig(ui, repo, dest, *args, **pycompat.strkwargs(opts))
        if common.isremotebooksenabled(ui):
            if bookmark and scratchpush:
                other = hg.peer(repo, opts, destpath)
                fetchedbookmarks = other.listkeyspatterns(b'bookmarks',
                                                          patterns=[bookmark])
                remotescratchbookmarks.update(fetchedbookmarks)
            _saveremotebookmarks(repo, remotescratchbookmarks, destpath)
    if oldphasemove:
        exchange._localphasemove = oldphasemove
    return result
Example #24
0
def fastexport(ui, repo, *revs, **opts):
    """export repository as git fast-import stream

    This command lets you dump a repository as a human-readable text stream.
    It can be piped into corresponding import routines like "git fast-import".
    Incremental dumps can be created by using marks files.
    """
    opts = pycompat.byteskwargs(opts)

    revs += tuple(opts.get(b"rev", []))
    if not revs:
        revs = scmutil.revrange(repo, [b":"])
    else:
        revs = scmutil.revrange(repo, revs)
    if not revs:
        raise error.Abort(_(b"no revisions matched"))
    authorfile = opts.get(b"authormap")
    if authorfile:
        authormap = convcmd.readauthormap(ui, authorfile)
    else:
        authormap = {}

    import_marks = opts.get(b"import_marks")
    marks = {}
    if import_marks:
        with open(import_marks, "rb") as import_marks_file:
            for line in import_marks_file:
                line = line.strip()
                if not isrev.match(line) or line in marks:
                    raise error.Abort(_(b"Corrupted marks file"))
                marks[line] = len(marks) + 1

    revs.sort()
    with ui.makeprogress(_(b"exporting"),
                         unit=_(b"revisions"),
                         total=len(revs)) as progress:
        for rev in revs:
            export_commit(ui, repo, rev, marks, authormap)
            progress.increment()

    export_marks = opts.get(b"export_marks")
    if export_marks:
        with open(export_marks, "wb") as export_marks_file:
            output_marks = [None] * len(marks)
            for k, v in marks.items():
                output_marks[v - 1] = k
            for k in output_marks:
                export_marks_file.write(k + b"\n")
Example #25
0
def amend(ui, repo, *pats, **opts):
    """amend the working copy parent with all or specified outstanding changes

    Similar to :hg:`commit --amend`, but reuse the commit message without
    invoking editor, unless ``--edit`` was set.

    See :hg:`help commit` for more details.
    """
    opts = pycompat.byteskwargs(opts)
    cmdutil.checknotesize(ui, opts)

    with repo.wlock(), repo.lock():
        if not opts.get(b'logfile'):
            opts[b'message'] = opts.get(b'message') or repo[b'.'].description()
        opts[b'amend'] = True
        return commands._docommit(ui, repo, *pats, **pycompat.strkwargs(opts))
def amend(ui, repo, *pats, **opts):
    """amend the working copy parent with all or specified outstanding changes

    Similar to :hg:`commit --amend`, but reuse the commit message without
    invoking editor, unless ``--edit`` was set.

    See :hg:`help commit` for more details.
    """
    opts = pycompat.byteskwargs(opts)
    if len(opts['note']) > 255:
        raise error.Abort(_("cannot store a note of more than 255 bytes"))
    with repo.wlock(), repo.lock():
        if not opts.get('logfile'):
            opts['message'] = opts.get('message') or repo['.'].description()
        opts['amend'] = True
        return commands._docommit(ui, repo, *pats, **pycompat.strkwargs(opts))
Example #27
0
def _annotatewrapper(orig, ui, repo, *pats, **opts):
    """used by wrapdefault"""
    # we need this hack until the obsstore has 0.0 seconds perf impact
    if ui.configbool(b'fastannotate', b'unfilteredrepo'):
        repo = repo.unfiltered()

    # treat the file as text (skip the isbinary check)
    if ui.configbool(b'fastannotate', b'forcetext'):
        opts['text'] = True

    # check if we need to do prefetch (client-side)
    rev = opts.get('rev')
    if util.safehasattr(repo, 'prefetchfastannotate') and rev is not None:
        paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts)))
        repo.prefetchfastannotate(paths)

    return orig(ui, repo, *pats, **opts)
Example #28
0
def clonenarrowcmd(orig, ui, repo, *args, **opts):
    """Wraps clone command, so 'hg clone' first wraps localrepo.clone()."""
    opts = pycompat.byteskwargs(opts)
    wrappedextraprepare = util.nullcontextmanager()
    opts_narrow = opts['narrow']
    if opts_narrow:

        def pullbundle2extraprepare_widen(orig, pullop, kwargs):
            # Create narrow spec patterns from clone flags
            includepats = narrowspec.parsepatterns(opts['include'])
            excludepats = narrowspec.parsepatterns(opts['exclude'])

            # If necessary, ask the server to expand the narrowspec.
            includepats, excludepats = expandpull(pullop, includepats,
                                                  excludepats)

            if not includepats and excludepats:
                # If nothing was included, we assume the user meant to include
                # everything, except what they asked to exclude.
                includepats = {'path:.'}

            pullop.repo.setnarrowpats(includepats, excludepats)

            # This will populate 'includepats' etc with the values from the
            # narrowspec we just saved.
            orig(pullop, kwargs)

            if opts.get('depth'):
                kwargs['depth'] = opts['depth']

        wrappedextraprepare = extensions.wrappedfunction(
            exchange, '_pullbundle2extraprepare',
            pullbundle2extraprepare_widen)

    def pullnarrow(orig, repo, *args, **kwargs):
        if opts_narrow:
            repo.requirements.add(changegroup.NARROW_REQUIREMENT)
            repo._writerequirements()

        return orig(repo, *args, **kwargs)

    wrappedpull = extensions.wrappedfunction(exchange, 'pull', pullnarrow)

    with wrappedextraprepare, wrappedpull:
        return orig(ui, repo, *args, **pycompat.strkwargs(opts))
Example #29
0
def uncommit(ui, repo, *pats, **opts):
    """uncommit part or all of a local changeset

    This command undoes the effect of a local commit, returning the affected
    files to their uncommitted state. This means that files modified or
    deleted in the changeset will be left unchanged, and so will remain
    modified in the working directory.

    If no files are specified, the commit will be pruned, unless --keep is
    given.
    """
    opts = pycompat.byteskwargs(opts)

    with repo.wlock(), repo.lock():

        if not pats and not repo.ui.configbool('experimental',
                                               'uncommitondirtywdir'):
            cmdutil.bailifchanged(repo)
        old = repo['.']
        rewriteutil.precheck(repo, [old.rev()], 'uncommit')
        if len(old.parents()) > 1:
            raise error.Abort(_("cannot uncommit merge changeset"))

        with repo.transaction('uncommit'):
            match = scmutil.match(old, pats, opts)
            keepcommit = opts.get('keep') or pats
            newid = _commitfiltered(repo, old, match, keepcommit)
            if newid is None:
                ui.status(_("nothing to uncommit\n"))
                return 1

            mapping = {}
            if newid != old.p1().node():
                # Move local changes on filtered changeset
                mapping[old.node()] = (newid, )
            else:
                # Fully removed the old commit
                mapping[old.node()] = ()

            scmutil.cleanupnodes(repo, mapping, 'uncommit')

            with repo.dirstate.parentchange():
                repo.dirstate.setparents(newid, node.nullid)
                s = repo.status(old.p1(), old, match=match)
                _fixdirstate(repo, old, repo[newid], s)
Example #30
0
def clonenarrowcmd(orig, ui, repo, *args, **opts):
    """Wraps clone command, so 'hg clone' first wraps localrepo.clone()."""
    opts = pycompat.byteskwargs(opts)
    wrappedextraprepare = util.nullcontextmanager()
    narrowspecfile = opts[b'narrowspec']

    if narrowspecfile:
        filepath = os.path.join(encoding.getcwd(), narrowspecfile)
        ui.status(_(b"reading narrowspec from '%s'\n") % filepath)
        try:
            fdata = util.readfile(filepath)
        except IOError as inst:
            raise error.Abort(
                _(b"cannot read narrowspecs from '%s': %s") %
                (filepath, encoding.strtolocal(inst.strerror)))

        includes, excludes, profiles = sparse.parseconfig(ui, fdata, b'narrow')
        if profiles:
            raise error.Abort(
                _(b"cannot specify other files using '%include' in"
                  b" narrowspec"))

        narrowspec.validatepatterns(includes)
        narrowspec.validatepatterns(excludes)

        # narrowspec is passed so we should assume that user wants narrow clone
        opts[b'narrow'] = True
        opts[b'include'].extend(includes)
        opts[b'exclude'].extend(excludes)

    if opts[b'narrow']:

        def pullbundle2extraprepare_widen(orig, pullop, kwargs):
            orig(pullop, kwargs)

            if opts.get(b'depth'):
                kwargs[b'depth'] = opts[b'depth']

        wrappedextraprepare = extensions.wrappedfunction(
            exchange, b'_pullbundle2extraprepare',
            pullbundle2extraprepare_widen)

    with wrappedextraprepare:
        return orig(ui, repo, *args, **pycompat.strkwargs(opts))
Example #31
0
def mvcheck(orig, ui, repo, *pats, **opts):
    """Hook to check for moves at commit time"""
    opts = pycompat.byteskwargs(opts)
    renames = None
    disabled = opts.pop('no_automv', False)
    if not disabled:
        threshold = ui.configint('automv', 'similarity')
        if not 0 <= threshold <= 100:
            raise error.Abort(_('automv.similarity must be between 0 and 100'))
        if threshold > 0:
            match = scmutil.match(repo[None], pats, opts)
            added, removed = _interestingfiles(repo, match)
            renames = _findrenames(repo, match, added, removed,
                                   threshold / 100.0)

    with repo.wlock():
        if renames is not None:
            scmutil._markchanges(repo, (), (), renames)
        return orig(ui, repo, *pats, **pycompat.strkwargs(opts))
Example #32
0
 def __call__(self, ui, repo, *pats, **opts):
   opts = pycompat.byteskwargs(opts)
   options = ' '.join(map(procutil.shellquote, opts['option']))
   if options:
     options = ' ' + options
   return dodiff(ui, repo, self._cmdline + options, pats, opts)