Details
Details
- Reviewers
- None
- Group Reviewers
hg-reviewers - Commits
- rHG6a447a3d1bd0: addremove: pass around uipathfn and use instead of m.uipath() (API)
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
| hg-reviewers |
| Lint Skipped |
| Unit Tests Skipped |
| Path | Packages | |||
|---|---|---|---|---|
| M | contrib/perf.py (6 lines) | |||
| M | hgext/largefiles/overrides.py (6 lines) | |||
| M | mercurial/cmdutil.py (8 lines) | |||
| M | mercurial/commands.py (4 lines) | |||
| M | mercurial/scmutil.py (19 lines) | |||
| M | mercurial/subrepo.py (6 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| Martin von Zweigbergk | Feb 8 2019, 2:25 AM |
| Status | Author | Revision | |
|---|---|---|---|
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz | ||
| Closed | martinvonz |
| def perfaddremove(ui, repo, **opts): | def perfaddremove(ui, repo, **opts): | ||||
| opts = _byteskwargs(opts) | opts = _byteskwargs(opts) | ||||
| timer, fm = gettimer(ui, opts) | timer, fm = gettimer(ui, opts) | ||||
| try: | try: | ||||
| oldquiet = repo.ui.quiet | oldquiet = repo.ui.quiet | ||||
| repo.ui.quiet = True | repo.ui.quiet = True | ||||
| matcher = scmutil.match(repo[None]) | matcher = scmutil.match(repo[None]) | ||||
| opts[b'dry_run'] = True | opts[b'dry_run'] = True | ||||
| if b'uipathfn' in getargspec(scmutil.addremove).args: | |||||
| uipathfn = scmutil.getuipathfn(repo) | |||||
| timer(lambda: scmutil.addremove(repo, matcher, b"", uipathfn, opts)) | |||||
| else: | |||||
| timer(lambda: scmutil.addremove(repo, matcher, b"", opts)) | timer(lambda: scmutil.addremove(repo, matcher, b"", opts)) | ||||
| finally: | finally: | ||||
| repo.ui.quiet = oldquiet | repo.ui.quiet = oldquiet | ||||
| fm.end() | fm.end() | ||||
| def clearcaches(cl): | def clearcaches(cl): | ||||
| # behave somewhat consistently across internal API changes | # behave somewhat consistently across internal API changes | ||||
| if util.safehasattr(cl, b'clearcaches'): | if util.safehasattr(cl, b'clearcaches'): | ||||
| cl.clearcaches() | cl.clearcaches() | ||||
| def overridesummary(orig, ui, repo, *pats, **opts): | def overridesummary(orig, ui, repo, *pats, **opts): | ||||
| try: | try: | ||||
| repo.lfstatus = True | repo.lfstatus = True | ||||
| orig(ui, repo, *pats, **opts) | orig(ui, repo, *pats, **opts) | ||||
| finally: | finally: | ||||
| repo.lfstatus = False | repo.lfstatus = False | ||||
| @eh.wrapfunction(scmutil, 'addremove') | @eh.wrapfunction(scmutil, 'addremove') | ||||
| def scmutiladdremove(orig, repo, matcher, prefix, opts=None): | def scmutiladdremove(orig, repo, matcher, prefix, uipathfn, opts=None): | ||||
| if opts is None: | if opts is None: | ||||
| opts = {} | opts = {} | ||||
| if not lfutil.islfilesrepo(repo): | if not lfutil.islfilesrepo(repo): | ||||
| return orig(repo, matcher, prefix, opts) | return orig(repo, matcher, prefix, uipathfn, opts) | ||||
| # Get the list of missing largefiles so we can remove them | # Get the list of missing largefiles so we can remove them | ||||
| lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | ||||
| unsure, s = lfdirstate.status(matchmod.always(repo.root, repo.getcwd()), | unsure, s = lfdirstate.status(matchmod.always(repo.root, repo.getcwd()), | ||||
| subrepos=[], ignored=False, clean=False, | subrepos=[], ignored=False, clean=False, | ||||
| unknown=False) | unknown=False) | ||||
| # Call into the normal remove code, but the removing of the standin, we want | # Call into the normal remove code, but the removing of the standin, we want | ||||
| # to have handled by original addremove. Monkey patching here makes sure | # to have handled by original addremove. Monkey patching here makes sure | ||||
| # Call into the normal add code, and any files that *should* be added as | # Call into the normal add code, and any files that *should* be added as | ||||
| # largefiles will be | # largefiles will be | ||||
| added, bad = addlargefiles(repo.ui, repo, True, matcher, | added, bad = addlargefiles(repo.ui, repo, True, matcher, | ||||
| **pycompat.strkwargs(opts)) | **pycompat.strkwargs(opts)) | ||||
| # Now that we've handled largefiles, hand off to the original addremove | # Now that we've handled largefiles, hand off to the original addremove | ||||
| # function to take care of the rest. Make sure it doesn't do anything with | # function to take care of the rest. Make sure it doesn't do anything with | ||||
| # largefiles by passing a matcher that will ignore them. | # largefiles by passing a matcher that will ignore them. | ||||
| matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) | matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) | ||||
| return orig(repo, matcher, prefix, opts) | return orig(repo, matcher, prefix, uipathfn, opts) | ||||
| # Calling purge with --all will cause the largefiles to be deleted. | # Calling purge with --all will cause the largefiles to be deleted. | ||||
| # Override repo.status to prevent this from happening. | # Override repo.status to prevent this from happening. | ||||
| @eh.wrapcommand('purge', extension='purge') | @eh.wrapcommand('purge', extension='purge') | ||||
| def overridepurge(orig, ui, repo, *dirs, **opts): | def overridepurge(orig, ui, repo, *dirs, **opts): | ||||
| # XXX Monkey patching a repoview will not work. The assigned attribute will | # XXX Monkey patching a repoview will not work. The assigned attribute will | ||||
| # be set on the unfiltered repo, but we will only lookup attributes in the | # be set on the unfiltered repo, but we will only lookup attributes in the | ||||
| # unfiltered repo if the lookup in the repoview object itself fails. As the | # unfiltered repo if the lookup in the repoview object itself fails. As the | ||||
| dsguard = None | dsguard = None | ||||
| # extract addremove carefully -- this function can be called from a command | # extract addremove carefully -- this function can be called from a command | ||||
| # that doesn't support addremove | # that doesn't support addremove | ||||
| if opts.get('addremove'): | if opts.get('addremove'): | ||||
| dsguard = dirstateguard.dirstateguard(repo, 'commit') | dsguard = dirstateguard.dirstateguard(repo, 'commit') | ||||
| with dsguard or util.nullcontextmanager(): | with dsguard or util.nullcontextmanager(): | ||||
| if dsguard: | if dsguard: | ||||
| if scmutil.addremove(repo, matcher, "", opts) != 0: | relative = scmutil.anypats(pats, opts) | ||||
| uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative) | |||||
| if scmutil.addremove(repo, matcher, "", uipathfn, opts) != 0: | |||||
| raise error.Abort( | raise error.Abort( | ||||
| _("failed to mark all new/missing files as added/removed")) | _("failed to mark all new/missing files as added/removed")) | ||||
| return commitfunc(ui, repo, message, matcher, opts) | return commitfunc(ui, repo, message, matcher, opts) | ||||
| def samefile(f, ctx1, ctx2): | def samefile(f, ctx1, ctx2): | ||||
| if f in ctx1.manifest(): | if f in ctx1.manifest(): | ||||
| a = ctx1.filectx(f) | a = ctx1.filectx(f) | ||||
| files = set([fn for st in base.status(old)[:3] | files = set([fn for st in base.status(old)[:3] | ||||
| for fn in st]) | for fn in st]) | ||||
| else: | else: | ||||
| files = set(old.files()) | files = set(old.files()) | ||||
| # add/remove the files to the working copy if the "addremove" option | # add/remove the files to the working copy if the "addremove" option | ||||
| # was specified. | # was specified. | ||||
| matcher = scmutil.match(wctx, pats, opts) | matcher = scmutil.match(wctx, pats, opts) | ||||
| relative = scmutil.anypats(pats, opts) | |||||
| uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative) | |||||
| if (opts.get('addremove') | if (opts.get('addremove') | ||||
| and scmutil.addremove(repo, matcher, "", opts)): | and scmutil.addremove(repo, matcher, "", uipathfn, opts)): | ||||
| raise error.Abort( | raise error.Abort( | ||||
| _("failed to mark all new/missing files as added/removed")) | _("failed to mark all new/missing files as added/removed")) | ||||
| # Check subrepos. This depends on in-place wctx._status update in | # Check subrepos. This depends on in-place wctx._status update in | ||||
| # subrepo.precommit(). To minimize the risk of this hack, we do | # subrepo.precommit(). To minimize the risk of this hack, we do | ||||
| # nothing if .hgsub does not exist. | # nothing if .hgsub does not exist. | ||||
| if '.hgsub' in wctx or '.hgsub' in old: | if '.hgsub' in wctx or '.hgsub' in old: | ||||
| subs, commitsubs, newsubstate = subrepoutil.precommit( | subs, commitsubs, newsubstate = subrepoutil.precommit( | ||||
| R foobar.c | R foobar.c | ||||
| Returns 0 if all files are successfully added. | Returns 0 if all files are successfully added. | ||||
| """ | """ | ||||
| opts = pycompat.byteskwargs(opts) | opts = pycompat.byteskwargs(opts) | ||||
| if not opts.get('similarity'): | if not opts.get('similarity'): | ||||
| opts['similarity'] = '100' | opts['similarity'] = '100' | ||||
| matcher = scmutil.match(repo[None], pats, opts) | matcher = scmutil.match(repo[None], pats, opts) | ||||
| return scmutil.addremove(repo, matcher, "", opts) | relative = scmutil.anypats(pats, opts) | ||||
| uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative) | |||||
| return scmutil.addremove(repo, matcher, "", uipathfn, opts) | |||||
| @command('annotate|blame', | @command('annotate|blame', | ||||
| [('r', 'rev', '', _('annotate the specified revision'), _('REV')), | [('r', 'rev', '', _('annotate the specified revision'), _('REV')), | ||||
| ('', 'follow', None, | ('', 'follow', None, | ||||
| _('follow copies/renames and list the filename (DEPRECATED)')), | _('follow copies/renames and list the filename (DEPRECATED)')), | ||||
| ('', 'no-follow', None, _("don't follow copies and renames")), | ('', 'no-follow', None, _("don't follow copies and renames")), | ||||
| ('a', 'text', None, _('treat all files as text')), | ('a', 'text', None, _('treat all files as text')), | ||||
| ('u', 'user', None, _('list the author (long with -v)')), | ('u', 'user', None, _('list the author (long with -v)')), | ||||
| return lambda f: pathto(f, cwd) | return lambda f: pathto(f, cwd) | ||||
| else: | else: | ||||
| return lambda f: f | return lambda f: f | ||||
| def subdiruipathfn(subpath, uipathfn): | def subdiruipathfn(subpath, uipathfn): | ||||
| '''Create a new uipathfn that treats the file as relative to subpath.''' | '''Create a new uipathfn that treats the file as relative to subpath.''' | ||||
| return lambda f: uipathfn(posixpath.join(subpath, f)) | return lambda f: uipathfn(posixpath.join(subpath, f)) | ||||
| def anypats(pats, opts): | |||||
| '''Checks if any patterns, including --include and --exclude were given. | |||||
| Some commands (e.g. addremove) use this condition for deciding whether to | |||||
| print absolute or relative paths. | |||||
| ''' | |||||
| return bool(pats or opts.get('include') or opts.get('exclude')) | |||||
| def expandpats(pats): | def expandpats(pats): | ||||
| '''Expand bare globs when running on windows. | '''Expand bare globs when running on windows. | ||||
| On posix we assume it already has already been done by sh.''' | On posix we assume it already has already been done by sh.''' | ||||
| if not util.expandglobs: | if not util.expandglobs: | ||||
| return list(pats) | return list(pats) | ||||
| ret = [] | ret = [] | ||||
| for kindpat in pats: | for kindpat in pats: | ||||
| kind, pat = matchmod._patsplit(kindpat, None) | kind, pat = matchmod._patsplit(kindpat, None) | ||||
| metadata=metadata) | metadata=metadata) | ||||
| else: | else: | ||||
| from . import repair # avoid import cycle | from . import repair # avoid import cycle | ||||
| tostrip = list(n for ns in replacements for n in ns) | tostrip = list(n for ns in replacements for n in ns) | ||||
| if tostrip: | if tostrip: | ||||
| repair.delayedstrip(repo.ui, repo, tostrip, operation, | repair.delayedstrip(repo.ui, repo, tostrip, operation, | ||||
| backup=backup) | backup=backup) | ||||
| def addremove(repo, matcher, prefix, opts=None): | def addremove(repo, matcher, prefix, uipathfn, opts=None): | ||||
| if opts is None: | if opts is None: | ||||
| opts = {} | opts = {} | ||||
| m = matcher | m = matcher | ||||
| dry_run = opts.get('dry_run') | dry_run = opts.get('dry_run') | ||||
| try: | try: | ||||
| similarity = float(opts.get('similarity') or 0) | similarity = float(opts.get('similarity') or 0) | ||||
| except ValueError: | except ValueError: | ||||
| raise error.Abort(_('similarity must be a number')) | raise error.Abort(_('similarity must be a number')) | ||||
| if similarity < 0 or similarity > 100: | if similarity < 0 or similarity > 100: | ||||
| raise error.Abort(_('similarity must be between 0 and 100')) | raise error.Abort(_('similarity must be between 0 and 100')) | ||||
| similarity /= 100.0 | similarity /= 100.0 | ||||
| ret = 0 | ret = 0 | ||||
| wctx = repo[None] | wctx = repo[None] | ||||
| for subpath in sorted(wctx.substate): | for subpath in sorted(wctx.substate): | ||||
| submatch = matchmod.subdirmatcher(subpath, m) | submatch = matchmod.subdirmatcher(subpath, m) | ||||
| if opts.get('subrepos') or m.exact(subpath) or any(submatch.files()): | if opts.get('subrepos') or m.exact(subpath) or any(submatch.files()): | ||||
| sub = wctx.sub(subpath) | sub = wctx.sub(subpath) | ||||
| subprefix = repo.wvfs.reljoin(prefix, subpath) | subprefix = repo.wvfs.reljoin(prefix, subpath) | ||||
| subuipathfn = subdiruipathfn(subpath, uipathfn) | |||||
| try: | try: | ||||
| if sub.addremove(submatch, subprefix, opts): | if sub.addremove(submatch, subprefix, subuipathfn, opts): | ||||
| ret = 1 | ret = 1 | ||||
| except error.LookupError: | except error.LookupError: | ||||
| repo.ui.status(_("skipping missing subrepository: %s\n") | repo.ui.status(_("skipping missing subrepository: %s\n") | ||||
| % m.uipath(subpath)) | % uipathfn(subpath)) | ||||
| rejected = [] | rejected = [] | ||||
| def badfn(f, msg): | def badfn(f, msg): | ||||
| if f in m.files(): | if f in m.files(): | ||||
| m.bad(f, msg) | m.bad(f, msg) | ||||
| rejected.append(f) | rejected.append(f) | ||||
| badmatch = matchmod.badmatch(m, badfn) | badmatch = matchmod.badmatch(m, badfn) | ||||
| added, unknown, deleted, removed, forgotten = _interestingfiles(repo, | added, unknown, deleted, removed, forgotten = _interestingfiles(repo, | ||||
| badmatch) | badmatch) | ||||
| unknownset = set(unknown + forgotten) | unknownset = set(unknown + forgotten) | ||||
| toprint = unknownset.copy() | toprint = unknownset.copy() | ||||
| toprint.update(deleted) | toprint.update(deleted) | ||||
| for abs in sorted(toprint): | for abs in sorted(toprint): | ||||
| if repo.ui.verbose or not m.exact(abs): | if repo.ui.verbose or not m.exact(abs): | ||||
| if abs in unknownset: | if abs in unknownset: | ||||
| status = _('adding %s\n') % m.uipath(abs) | status = _('adding %s\n') % uipathfn(abs) | ||||
| label = 'ui.addremove.added' | label = 'ui.addremove.added' | ||||
| else: | else: | ||||
| status = _('removing %s\n') % m.uipath(abs) | status = _('removing %s\n') % uipathfn(abs) | ||||
| label = 'ui.addremove.removed' | label = 'ui.addremove.removed' | ||||
| repo.ui.status(status, label=label) | repo.ui.status(status, label=label) | ||||
| renames = _findrenames(repo, m, added + unknown, removed + deleted, | renames = _findrenames(repo, m, added + unknown, removed + deleted, | ||||
| similarity) | similarity) | ||||
| if not dry_run: | if not dry_run: | ||||
| _markchanges(repo, unknown + forgotten, deleted, renames) | _markchanges(repo, unknown + forgotten, deleted, renames) | ||||
| This may be a no-op on some systems. | This may be a no-op on some systems. | ||||
| """ | """ | ||||
| raise NotImplementedError | raise NotImplementedError | ||||
| def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): | def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): | ||||
| return [] | return [] | ||||
| def addremove(self, matcher, prefix, opts): | def addremove(self, matcher, prefix, uipathfn, opts): | ||||
| self.ui.warn("%s: %s" % (prefix, _("addremove is not supported"))) | self.ui.warn("%s: %s" % (prefix, _("addremove is not supported"))) | ||||
| return 1 | return 1 | ||||
| def cat(self, match, fm, fntemplate, prefix, **opts): | def cat(self, match, fm, fntemplate, prefix, **opts): | ||||
| return 1 | return 1 | ||||
| def status(self, rev2, **opts): | def status(self, rev2, **opts): | ||||
| return scmutil.status([], [], [], [], [], [], []) | return scmutil.status([], [], [], [], [], [], []) | ||||
| self._repo.vfs.write('hgrc', util.tonativeeol(''.join(lines))) | self._repo.vfs.write('hgrc', util.tonativeeol(''.join(lines))) | ||||
| @annotatesubrepoerror | @annotatesubrepoerror | ||||
| def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): | def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): | ||||
| return cmdutil.add(ui, self._repo, match, prefix, uipathfn, | return cmdutil.add(ui, self._repo, match, prefix, uipathfn, | ||||
| explicitonly, **opts) | explicitonly, **opts) | ||||
| @annotatesubrepoerror | @annotatesubrepoerror | ||||
| def addremove(self, m, prefix, opts): | def addremove(self, m, prefix, uipathfn, opts): | ||||
| # In the same way as sub directories are processed, once in a subrepo, | # In the same way as sub directories are processed, once in a subrepo, | ||||
| # always entry any of its subrepos. Don't corrupt the options that will | # always entry any of its subrepos. Don't corrupt the options that will | ||||
| # be used to process sibling subrepos however. | # be used to process sibling subrepos however. | ||||
| opts = copy.copy(opts) | opts = copy.copy(opts) | ||||
| opts['subrepos'] = True | opts['subrepos'] = True | ||||
| return scmutil.addremove(self._repo, m, prefix, opts) | return scmutil.addremove(self._repo, m, prefix, uipathfn, opts) | ||||
| @annotatesubrepoerror | @annotatesubrepoerror | ||||
| def cat(self, match, fm, fntemplate, prefix, **opts): | def cat(self, match, fm, fntemplate, prefix, **opts): | ||||
| rev = self._state[1] | rev = self._state[1] | ||||
| ctx = self._repo[rev] | ctx = self._repo[rev] | ||||
| return cmdutil.cat(self.ui, self._repo, ctx, match, fm, fntemplate, | return cmdutil.cat(self.ui, self._repo, ctx, match, fm, fntemplate, | ||||
| prefix, **opts) | prefix, **opts) | ||||