Mercurial > public > mercurial-scm > hg
comparison mercurial/cmdutil.py @ 41605:7068c6b0114b
revert: respect ui.relative-paths
Differential Revision: https://phab.mercurial-scm.org/D5874
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Tue, 05 Feb 2019 10:30:05 -0800 |
parents | 9e545c9a4dfe |
children | 93620a4ba88d |
comparison
equal
deleted
inserted
replaced
41604:e944cf4ce1a8 | 41605:7068c6b0114b |
---|---|
2780 | 2780 |
2781 # `names` is a mapping for all elements in working copy and target revision | 2781 # `names` is a mapping for all elements in working copy and target revision |
2782 # The mapping is in the form: | 2782 # The mapping is in the form: |
2783 # <abs path in repo> -> (<path from CWD>, <exactly specified by matcher?>) | 2783 # <abs path in repo> -> (<path from CWD>, <exactly specified by matcher?>) |
2784 names = {} | 2784 names = {} |
2785 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) | |
2785 | 2786 |
2786 with repo.wlock(): | 2787 with repo.wlock(): |
2787 ## filling of the `names` mapping | 2788 ## filling of the `names` mapping |
2788 # walk dirstate to fill `names` | 2789 # walk dirstate to fill `names` |
2789 | 2790 |
2795 targetsubs = sorted(s for s in wctx.substate if m(s)) | 2796 targetsubs = sorted(s for s in wctx.substate if m(s)) |
2796 | 2797 |
2797 if not m.always(): | 2798 if not m.always(): |
2798 matcher = matchmod.badmatch(m, lambda x, y: False) | 2799 matcher = matchmod.badmatch(m, lambda x, y: False) |
2799 for abs in wctx.walk(matcher): | 2800 for abs in wctx.walk(matcher): |
2800 names[abs] = m.rel(abs), m.exact(abs) | 2801 names[abs] = m.exact(abs) |
2801 | 2802 |
2802 # walk target manifest to fill `names` | 2803 # walk target manifest to fill `names` |
2803 | 2804 |
2804 def badfn(path, msg): | 2805 def badfn(path, msg): |
2805 if path in names: | 2806 if path in names: |
2812 return | 2813 return |
2813 ui.warn("%s: %s\n" % (m.rel(path), msg)) | 2814 ui.warn("%s: %s\n" % (m.rel(path), msg)) |
2814 | 2815 |
2815 for abs in ctx.walk(matchmod.badmatch(m, badfn)): | 2816 for abs in ctx.walk(matchmod.badmatch(m, badfn)): |
2816 if abs not in names: | 2817 if abs not in names: |
2817 names[abs] = m.rel(abs), m.exact(abs) | 2818 names[abs] = m.exact(abs) |
2818 | 2819 |
2819 # Find status of all file in `names`. | 2820 # Find status of all file in `names`. |
2820 m = scmutil.matchfiles(repo, names) | 2821 m = scmutil.matchfiles(repo, names) |
2821 | 2822 |
2822 changes = repo.status(node1=node, match=m, | 2823 changes = repo.status(node1=node, match=m, |
2823 unknown=True, ignored=True, clean=True) | 2824 unknown=True, ignored=True, clean=True) |
2824 else: | 2825 else: |
2825 changes = repo.status(node1=node, match=m) | 2826 changes = repo.status(node1=node, match=m) |
2826 for kind in changes: | 2827 for kind in changes: |
2827 for abs in kind: | 2828 for abs in kind: |
2828 names[abs] = m.rel(abs), m.exact(abs) | 2829 names[abs] = m.exact(abs) |
2829 | 2830 |
2830 m = scmutil.matchfiles(repo, names) | 2831 m = scmutil.matchfiles(repo, names) |
2831 | 2832 |
2832 modified = set(changes.modified) | 2833 modified = set(changes.modified) |
2833 added = set(changes.added) | 2834 added = set(changes.added) |
2885 mergeadd.remove(path) | 2886 mergeadd.remove(path) |
2886 dsadded |= mergeadd | 2887 dsadded |= mergeadd |
2887 dsmodified -= mergeadd | 2888 dsmodified -= mergeadd |
2888 | 2889 |
2889 # if f is a rename, update `names` to also revert the source | 2890 # if f is a rename, update `names` to also revert the source |
2890 cwd = repo.getcwd() | |
2891 for f in localchanges: | 2891 for f in localchanges: |
2892 src = repo.dirstate.copied(f) | 2892 src = repo.dirstate.copied(f) |
2893 # XXX should we check for rename down to target node? | 2893 # XXX should we check for rename down to target node? |
2894 if src and src not in names and repo.dirstate[src] == 'r': | 2894 if src and src not in names and repo.dirstate[src] == 'r': |
2895 dsremoved.add(src) | 2895 dsremoved.add(src) |
2896 names[src] = (repo.pathto(src, cwd), True) | 2896 names[src] = True |
2897 | 2897 |
2898 # determine the exact nature of the deleted changesets | 2898 # determine the exact nature of the deleted changesets |
2899 deladded = set(_deleted) | 2899 deladded = set(_deleted) |
2900 for path in _deleted: | 2900 for path in _deleted: |
2901 if path in mf: | 2901 if path in mf: |
2998 (clean, actions['noop'], discard), | 2998 (clean, actions['noop'], discard), |
2999 # Existing file, not tracked anywhere | 2999 # Existing file, not tracked anywhere |
3000 (unknown, actions['unknown'], discard), | 3000 (unknown, actions['unknown'], discard), |
3001 ) | 3001 ) |
3002 | 3002 |
3003 for abs, (rel, exact) in sorted(names.items()): | 3003 for abs, exact in sorted(names.items()): |
3004 # target file to be touch on disk (relative to cwd) | 3004 # target file to be touch on disk (relative to cwd) |
3005 target = repo.wjoin(abs) | 3005 target = repo.wjoin(abs) |
3006 # search the entry in the dispatch table. | 3006 # search the entry in the dispatch table. |
3007 # if the file is in any of these sets, it was touched in the working | 3007 # if the file is in any of these sets, it was touched in the working |
3008 # directory parent and we are sure it needs to be reverted. | 3008 # directory parent and we are sure it needs to be reverted. |
3015 # If in interactive mode, don't automatically create | 3015 # If in interactive mode, don't automatically create |
3016 # .orig files (issue4793) | 3016 # .orig files (issue4793) |
3017 if dobackup == backupinteractive: | 3017 if dobackup == backupinteractive: |
3018 tobackup.add(abs) | 3018 tobackup.add(abs) |
3019 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])): | 3019 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])): |
3020 bakname = scmutil.backuppath(ui, repo, abs) | 3020 absbakname = scmutil.backuppath(ui, repo, abs) |
3021 relbakname = os.path.relpath(bakname) | 3021 bakname = os.path.relpath(absbakname, |
3022 start=repo.root) | |
3022 ui.note(_('saving current version of %s as %s\n') % | 3023 ui.note(_('saving current version of %s as %s\n') % |
3023 (rel, relbakname)) | 3024 (uipathfn(abs), uipathfn(bakname))) |
3024 if not opts.get('dry_run'): | 3025 if not opts.get('dry_run'): |
3025 if interactive: | 3026 if interactive: |
3026 util.copyfile(target, bakname) | 3027 util.copyfile(target, absbakname) |
3027 else: | 3028 else: |
3028 util.rename(target, bakname) | 3029 util.rename(target, absbakname) |
3029 if opts.get('dry_run'): | 3030 if opts.get('dry_run'): |
3030 if ui.verbose or not exact: | 3031 if ui.verbose or not exact: |
3031 ui.status(msg % rel) | 3032 ui.status(msg % uipathfn(abs)) |
3032 elif exact: | 3033 elif exact: |
3033 ui.warn(msg % rel) | 3034 ui.warn(msg % uipathfn(abs)) |
3034 break | 3035 break |
3035 | 3036 |
3036 if not opts.get('dry_run'): | 3037 if not opts.get('dry_run'): |
3037 needdata = ('revert', 'add', 'undelete') | 3038 needdata = ('revert', 'add', 'undelete') |
3038 oplist = [actions[name][0] for name in needdata] | 3039 oplist = [actions[name][0] for name in needdata] |
3039 prefetch = scmutil.prefetchfiles | 3040 prefetch = scmutil.prefetchfiles |
3040 matchfiles = scmutil.matchfiles | 3041 matchfiles = scmutil.matchfiles |
3041 prefetch(repo, [ctx.rev()], | 3042 prefetch(repo, [ctx.rev()], |
3042 matchfiles(repo, | 3043 matchfiles(repo, |
3043 [f for sublist in oplist for f in sublist])) | 3044 [f for sublist in oplist for f in sublist])) |
3044 _performrevert(repo, parents, ctx, names, actions, interactive, | 3045 _performrevert(repo, parents, ctx, names, uipathfn, actions, |
3045 tobackup) | 3046 interactive, tobackup) |
3046 | 3047 |
3047 if targetsubs: | 3048 if targetsubs: |
3048 # Revert the subrepos on the revert list | 3049 # Revert the subrepos on the revert list |
3049 for sub in targetsubs: | 3050 for sub in targetsubs: |
3050 try: | 3051 try: |
3052 **pycompat.strkwargs(opts)) | 3053 **pycompat.strkwargs(opts)) |
3053 except KeyError: | 3054 except KeyError: |
3054 raise error.Abort("subrepository '%s' does not exist in %s!" | 3055 raise error.Abort("subrepository '%s' does not exist in %s!" |
3055 % (sub, short(ctx.node()))) | 3056 % (sub, short(ctx.node()))) |
3056 | 3057 |
3057 def _performrevert(repo, parents, ctx, names, actions, interactive=False, | 3058 def _performrevert(repo, parents, ctx, names, uipathfn, actions, |
3058 tobackup=None): | 3059 interactive=False, tobackup=None): |
3059 """function that actually perform all the actions computed for revert | 3060 """function that actually perform all the actions computed for revert |
3060 | 3061 |
3061 This is an independent function to let extension to plug in and react to | 3062 This is an independent function to let extension to plug in and react to |
3062 the imminent revert. | 3063 the imminent revert. |
3063 | 3064 |
3078 except OSError: | 3079 except OSError: |
3079 pass | 3080 pass |
3080 repo.dirstate.remove(f) | 3081 repo.dirstate.remove(f) |
3081 | 3082 |
3082 def prntstatusmsg(action, f): | 3083 def prntstatusmsg(action, f): |
3083 rel, exact = names[f] | 3084 exact = names[f] |
3084 if repo.ui.verbose or not exact: | 3085 if repo.ui.verbose or not exact: |
3085 repo.ui.status(actions[action][1] % rel) | 3086 repo.ui.status(actions[action][1] % uipathfn(f)) |
3086 | 3087 |
3087 audit_path = pathutil.pathauditor(repo.root, cached=True) | 3088 audit_path = pathutil.pathauditor(repo.root, cached=True) |
3088 for f in actions['forget'][0]: | 3089 for f in actions['forget'][0]: |
3089 if interactive: | 3090 if interactive: |
3090 choice = repo.ui.promptchoice( | 3091 choice = repo.ui.promptchoice( |
3091 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f) | 3092 _("forget added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f)) |
3092 if choice == 0: | 3093 if choice == 0: |
3093 prntstatusmsg('forget', f) | 3094 prntstatusmsg('forget', f) |
3094 repo.dirstate.drop(f) | 3095 repo.dirstate.drop(f) |
3095 else: | 3096 else: |
3096 excluded_files.append(f) | 3097 excluded_files.append(f) |
3099 repo.dirstate.drop(f) | 3100 repo.dirstate.drop(f) |
3100 for f in actions['remove'][0]: | 3101 for f in actions['remove'][0]: |
3101 audit_path(f) | 3102 audit_path(f) |
3102 if interactive: | 3103 if interactive: |
3103 choice = repo.ui.promptchoice( | 3104 choice = repo.ui.promptchoice( |
3104 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f) | 3105 _("remove added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f)) |
3105 if choice == 0: | 3106 if choice == 0: |
3106 prntstatusmsg('remove', f) | 3107 prntstatusmsg('remove', f) |
3107 doremove(f) | 3108 doremove(f) |
3108 else: | 3109 else: |
3109 excluded_files.append(f) | 3110 excluded_files.append(f) |