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