Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/cmdutil.py @ 21575:8262c2a39ab8
revert: add some inline comments
I spend some time understanding how this part of the revert code is
working. I'm adding some comments to help the code readability. I
expect most of them to disappear in a coming refactoring. But the
refactoring should be easier to follow with the comment.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Tue, 13 May 2014 16:29:42 -0700 |
parents | 404ff404db79 |
children | 33395a7e5527 |
comparison
equal
deleted
inserted
replaced
21574:404ff404db79 | 21575:8262c2a39ab8 |
---|---|
2257 | 2257 |
2258 # need all matching names in dirstate and manifest of target rev, | 2258 # need all matching names in dirstate and manifest of target rev, |
2259 # so have to walk both. do not print errors if files exist in one | 2259 # so have to walk both. do not print errors if files exist in one |
2260 # but not other. | 2260 # but not other. |
2261 | 2261 |
2262 # `names` is a mapping for all elements in working copy and target revision | |
2263 # The mapping is in the form: | |
2264 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>) | |
2262 names = {} | 2265 names = {} |
2263 | 2266 |
2264 wlock = repo.wlock() | 2267 wlock = repo.wlock() |
2265 try: | 2268 try: |
2266 # walk dirstate. | 2269 ## filling of the `names` mapping |
2270 # walk dirstate to fill `names` | |
2267 | 2271 |
2268 m = scmutil.match(repo[None], pats, opts) | 2272 m = scmutil.match(repo[None], pats, opts) |
2269 m.bad = lambda x, y: False | 2273 m.bad = lambda x, y: False |
2270 for abs in repo.walk(m): | 2274 for abs in repo.walk(m): |
2271 names[abs] = m.rel(abs), m.exact(abs) | 2275 names[abs] = m.rel(abs), m.exact(abs) |
2272 | 2276 |
2273 # walk target manifest. | 2277 # walk target manifest to fill `names` |
2274 | 2278 |
2275 def badfn(path, msg): | 2279 def badfn(path, msg): |
2276 if path in names: | 2280 if path in names: |
2277 return | 2281 return |
2278 if path in ctx.substate: | 2282 if path in ctx.substate: |
2289 if abs not in names: | 2293 if abs not in names: |
2290 names[abs] = m.rel(abs), m.exact(abs) | 2294 names[abs] = m.rel(abs), m.exact(abs) |
2291 | 2295 |
2292 # get the list of subrepos that must be reverted | 2296 # get the list of subrepos that must be reverted |
2293 targetsubs = sorted(s for s in ctx.substate if m(s)) | 2297 targetsubs = sorted(s for s in ctx.substate if m(s)) |
2298 | |
2299 # Find status of all file in `names`. (Against working directory parent) | |
2294 m = scmutil.matchfiles(repo, names) | 2300 m = scmutil.matchfiles(repo, names) |
2295 changes = repo.status(match=m)[:4] | 2301 changes = repo.status(match=m)[:4] |
2296 modified, added, removed, deleted = map(set, changes) | 2302 modified, added, removed, deleted = map(set, changes) |
2297 | 2303 |
2298 # if f is a rename, also revert the source | 2304 # if f is a rename, update `names` to also revert the source |
2299 cwd = repo.getcwd() | 2305 cwd = repo.getcwd() |
2300 for f in added: | 2306 for f in added: |
2301 src = repo.dirstate.copied(f) | 2307 src = repo.dirstate.copied(f) |
2302 if src and src not in names and repo.dirstate[src] == 'r': | 2308 if src and src not in names and repo.dirstate[src] == 'r': |
2303 removed.add(src) | 2309 removed.add(src) |
2304 names[src] = (repo.pathto(src, cwd), True) | 2310 names[src] = (repo.pathto(src, cwd), True) |
2305 | 2311 |
2312 ## computation of the action to performs on `names` content. | |
2313 | |
2306 def removeforget(abs): | 2314 def removeforget(abs): |
2307 if repo.dirstate[abs] == 'a': | 2315 if repo.dirstate[abs] == 'a': |
2308 return _('forgetting %s\n') | 2316 return _('forgetting %s\n') |
2309 return _('removing %s\n') | 2317 return _('removing %s\n') |
2310 | 2318 |
2319 # action to be actually performed by revert | |
2320 # (<list of file>, message>) tuple | |
2311 revert = ([], _('reverting %s\n')) | 2321 revert = ([], _('reverting %s\n')) |
2312 add = ([], _('adding %s\n')) | 2322 add = ([], _('adding %s\n')) |
2313 remove = ([], removeforget) | 2323 remove = ([], removeforget) |
2314 undelete = ([], _('undeleting %s\n')) | 2324 undelete = ([], _('undeleting %s\n')) |
2315 | 2325 |
2325 (removed, undelete, None, True, False), | 2335 (removed, undelete, None, True, False), |
2326 (deleted, revert, remove, False, False), | 2336 (deleted, revert, remove, False, False), |
2327 ) | 2337 ) |
2328 | 2338 |
2329 for abs, (rel, exact) in sorted(names.items()): | 2339 for abs, (rel, exact) in sorted(names.items()): |
2340 # hash on file in target manifest (or None if missing from target) | |
2330 mfentry = mf.get(abs) | 2341 mfentry = mf.get(abs) |
2342 # target file to be touch on disk (relative to cwd) | |
2331 target = repo.wjoin(abs) | 2343 target = repo.wjoin(abs) |
2332 def handle(xlist, dobackup): | 2344 def handle(xlist, dobackup): |
2333 xlist[0].append(abs) | 2345 xlist[0].append(abs) |
2334 if (dobackup and not opts.get('no_backup') and | 2346 if (dobackup and not opts.get('no_backup') and |
2335 os.path.lexists(target) and | 2347 os.path.lexists(target) and |
2342 if ui.verbose or not exact: | 2354 if ui.verbose or not exact: |
2343 msg = xlist[1] | 2355 msg = xlist[1] |
2344 if not isinstance(msg, basestring): | 2356 if not isinstance(msg, basestring): |
2345 msg = msg(abs) | 2357 msg = msg(abs) |
2346 ui.status(msg % rel) | 2358 ui.status(msg % rel) |
2359 # search the entry in the dispatch table. | |
2360 # if the file is in any of this sets, it was touched in the working | |
2361 # directory parent and we are sure it needs to be reverted. | |
2347 for table, hitlist, misslist, backuphit, backupmiss in disptable: | 2362 for table, hitlist, misslist, backuphit, backupmiss in disptable: |
2348 if abs not in table: | 2363 if abs not in table: |
2349 continue | 2364 continue |
2350 # file has changed in dirstate | 2365 # file has changed in dirstate |
2351 if mfentry: | 2366 if mfentry: |
2352 handle(hitlist, backuphit) | 2367 handle(hitlist, backuphit) |
2353 elif misslist is not None: | 2368 elif misslist is not None: |
2354 handle(misslist, backupmiss) | 2369 handle(misslist, backupmiss) |
2355 break | 2370 break |
2356 else: | 2371 else: |
2372 # Not touched in current dirstate. | |
2373 | |
2374 # file is unknown in parent, restore older version or ignore. | |
2357 if abs not in repo.dirstate: | 2375 if abs not in repo.dirstate: |
2358 if mfentry: | 2376 if mfentry: |
2359 handle(add, True) | 2377 handle(add, True) |
2360 elif exact: | 2378 elif exact: |
2361 ui.warn(_('file not managed: %s\n') % rel) | 2379 ui.warn(_('file not managed: %s\n') % rel) |
2362 continue | 2380 continue |
2363 # file has not changed in dirstate | 2381 |
2382 # parent is target, no changes mean no changes | |
2364 if node == parent: | 2383 if node == parent: |
2365 if exact: | 2384 if exact: |
2366 ui.warn(_('no changes needed to %s\n') % rel) | 2385 ui.warn(_('no changes needed to %s\n') % rel) |
2367 continue | 2386 continue |
2387 # no change in dirstate but parent and target may differ | |
2368 if pmf is None: | 2388 if pmf is None: |
2369 # only need parent manifest in this unlikely case, | 2389 # only need parent manifest in this unlikely case, |
2370 # so do not read by default | 2390 # so do not read by default |
2371 pmf = repo[parent].manifest() | 2391 pmf = repo[parent].manifest() |
2372 if abs in pmf and mfentry: | 2392 if abs in pmf and mfentry: |