comparison mercurial/cmdutil.py @ 39405:cb70501d8b71

revert: fix the inconsistency of status msgs in --interactive mode Before this patch we were priting every action msg before actually performing that action and that was resulting in inconsistencies; like in --interactive session if user decided to not revert any changes in a file foo, still there will be a msg on console saying "reverting foo". To fix this, I have made some changes to print status msg just before the action it is going to perform, no matter if --interactive or not. Changes made in test-revert-interactive.t reflect the changed behavior. There are also some changes in test-revert.t because of change in the order of messages. Differential Revision: https://phab.mercurial-scm.org/D4380
author Sushil khanchi <sushilkhanchi97@gmail.com>
date Fri, 31 Aug 2018 23:28:09 +0530
parents 90afd61ef8a2
children 1cbe19eb496d
comparison
equal deleted inserted replaced
39404:90afd61ef8a2 39405:cb70501d8b71
3017 if not opts.get('dry_run'): 3017 if not opts.get('dry_run'):
3018 if interactive: 3018 if interactive:
3019 util.copyfile(target, bakname) 3019 util.copyfile(target, bakname)
3020 else: 3020 else:
3021 util.rename(target, bakname) 3021 util.rename(target, bakname)
3022 if ui.verbose or not exact: 3022 if opts.get('dry_run'):
3023 ui.status(msg % rel) 3023 if ui.verbose or not exact:
3024 ui.status(msg % rel)
3024 elif exact: 3025 elif exact:
3025 ui.warn(msg % rel) 3026 ui.warn(msg % rel)
3026 break 3027 break
3027 3028
3028 if not opts.get('dry_run'): 3029 if not opts.get('dry_run'):
3031 prefetch = scmutil.prefetchfiles 3032 prefetch = scmutil.prefetchfiles
3032 matchfiles = scmutil.matchfiles 3033 matchfiles = scmutil.matchfiles
3033 prefetch(repo, [ctx.rev()], 3034 prefetch(repo, [ctx.rev()],
3034 matchfiles(repo, 3035 matchfiles(repo,
3035 [f for sublist in oplist for f in sublist])) 3036 [f for sublist in oplist for f in sublist]))
3036 _performrevert(repo, parents, ctx, actions, interactive, tobackup) 3037 _performrevert(repo, parents, ctx, names, actions, interactive,
3038 tobackup)
3037 3039
3038 if targetsubs: 3040 if targetsubs:
3039 # Revert the subrepos on the revert list 3041 # Revert the subrepos on the revert list
3040 for sub in targetsubs: 3042 for sub in targetsubs:
3041 try: 3043 try:
3043 **pycompat.strkwargs(opts)) 3045 **pycompat.strkwargs(opts))
3044 except KeyError: 3046 except KeyError:
3045 raise error.Abort("subrepository '%s' does not exist in %s!" 3047 raise error.Abort("subrepository '%s' does not exist in %s!"
3046 % (sub, short(ctx.node()))) 3048 % (sub, short(ctx.node())))
3047 3049
3048 def _performrevert(repo, parents, ctx, actions, interactive=False, 3050 def _performrevert(repo, parents, ctx, names, actions, interactive=False,
3049 tobackup=None): 3051 tobackup=None):
3050 """function that actually perform all the actions computed for revert 3052 """function that actually perform all the actions computed for revert
3051 3053
3052 This is an independent function to let extension to plug in and react to 3054 This is an independent function to let extension to plug in and react to
3053 the imminent revert. 3055 the imminent revert.
3068 repo.wvfs.unlinkpath(f, rmdir=rmdir) 3070 repo.wvfs.unlinkpath(f, rmdir=rmdir)
3069 except OSError: 3071 except OSError:
3070 pass 3072 pass
3071 repo.dirstate.remove(f) 3073 repo.dirstate.remove(f)
3072 3074
3075 def prntstatusmsg(action, f):
3076 rel, exact = names[f]
3077 if repo.ui.verbose or not exact:
3078 repo.ui.status(actions[action][1] % rel)
3079
3073 audit_path = pathutil.pathauditor(repo.root, cached=True) 3080 audit_path = pathutil.pathauditor(repo.root, cached=True)
3074 for f in actions['forget'][0]: 3081 for f in actions['forget'][0]:
3075 if interactive: 3082 if interactive:
3076 choice = repo.ui.promptchoice( 3083 choice = repo.ui.promptchoice(
3077 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f) 3084 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3078 if choice == 0: 3085 if choice == 0:
3086 prntstatusmsg('forget', f)
3079 repo.dirstate.drop(f) 3087 repo.dirstate.drop(f)
3080 else: 3088 else:
3081 excluded_files.append(f) 3089 excluded_files.append(f)
3082 else: 3090 else:
3091 prntstatusmsg('forget', f)
3083 repo.dirstate.drop(f) 3092 repo.dirstate.drop(f)
3084 for f in actions['remove'][0]: 3093 for f in actions['remove'][0]:
3085 audit_path(f) 3094 audit_path(f)
3086 if interactive: 3095 if interactive:
3087 choice = repo.ui.promptchoice( 3096 choice = repo.ui.promptchoice(
3088 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f) 3097 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3089 if choice == 0: 3098 if choice == 0:
3099 prntstatusmsg('remove', f)
3090 doremove(f) 3100 doremove(f)
3091 else: 3101 else:
3092 excluded_files.append(f) 3102 excluded_files.append(f)
3093 else: 3103 else:
3104 prntstatusmsg('remove', f)
3094 doremove(f) 3105 doremove(f)
3095 for f in actions['drop'][0]: 3106 for f in actions['drop'][0]:
3096 audit_path(f) 3107 audit_path(f)
3108 prntstatusmsg('drop', f)
3097 repo.dirstate.remove(f) 3109 repo.dirstate.remove(f)
3098 3110
3099 normal = None 3111 normal = None
3100 if node == parent: 3112 if node == parent:
3101 # We're reverting to our parent. If possible, we'd like status 3113 # We're reverting to our parent. If possible, we'd like status
3138 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks) 3150 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3139 if tobackup is None: 3151 if tobackup is None:
3140 tobackup = set() 3152 tobackup = set()
3141 # Apply changes 3153 # Apply changes
3142 fp = stringio() 3154 fp = stringio()
3155 # `fnames` keeps track of filenames for which we have initiated changes,
3156 # to make sure that we print status msg only once per file.
3157 fnames = set()
3143 for c in chunks: 3158 for c in chunks:
3144 # Create a backup file only if this hunk should be backed up 3159 if ishunk(c):
3145 if ishunk(c) and c.header.filename() in tobackup:
3146 abs = c.header.filename() 3160 abs = c.header.filename()
3147 target = repo.wjoin(abs) 3161 if abs not in fnames:
3148 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs)) 3162 fnames.add(abs)
3149 util.copyfile(target, bakname) 3163 prntstatusmsg('revert', abs)
3150 tobackup.remove(abs) 3164 # Create a backup file only if this hunk should be backed up
3165 if c.header.filename() in tobackup:
3166 target = repo.wjoin(abs)
3167 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3168 util.copyfile(target, bakname)
3169 tobackup.remove(abs)
3151 c.write(fp) 3170 c.write(fp)
3152 dopatch = fp.tell() 3171 dopatch = fp.tell()
3153 fp.seek(0) 3172 fp.seek(0)
3154 if dopatch: 3173 if dopatch:
3155 try: 3174 try:
3157 except error.PatchError as err: 3176 except error.PatchError as err:
3158 raise error.Abort(pycompat.bytestr(err)) 3177 raise error.Abort(pycompat.bytestr(err))
3159 del fp 3178 del fp
3160 else: 3179 else:
3161 for f in actions['revert'][0]: 3180 for f in actions['revert'][0]:
3181 prntstatusmsg('revert', f)
3162 checkout(f) 3182 checkout(f)
3163 if normal: 3183 if normal:
3164 normal(f) 3184 normal(f)
3165 3185
3166 for f in actions['add'][0]: 3186 for f in actions['add'][0]:
3167 # Don't checkout modified files, they are already created by the diff 3187 # Don't checkout modified files, they are already created by the diff
3168 if f not in newlyaddedandmodifiedfiles: 3188 if f not in newlyaddedandmodifiedfiles:
3189 prntstatusmsg('add', f)
3169 checkout(f) 3190 checkout(f)
3170 repo.dirstate.add(f) 3191 repo.dirstate.add(f)
3171 3192
3172 normal = repo.dirstate.normallookup 3193 normal = repo.dirstate.normallookup
3173 if node == parent and p2 == nullid: 3194 if node == parent and p2 == nullid:
3174 normal = repo.dirstate.normal 3195 normal = repo.dirstate.normal
3175 for f in actions['undelete'][0]: 3196 for f in actions['undelete'][0]:
3197 prntstatusmsg('undelete', f)
3176 checkout(f) 3198 checkout(f)
3177 normal(f) 3199 normal(f)
3178 3200
3179 copied = copies.pathcopies(repo[parent], ctx) 3201 copied = copies.pathcopies(repo[parent], ctx)
3180 3202