407 ): |
407 ): |
408 |
408 |
409 subrepos = opts.get(b'subrepos') |
409 subrepos = opts.get(b'subrepos') |
410 |
410 |
411 # calculate list of files changed between both revs |
411 # calculate list of files changed between both revs |
412 st = repo.status(node1a, node2, matcher, listsubrepos=subrepos) |
412 st = ctx1a.status(ctx2, matcher, listsubrepos=subrepos) |
413 mod_a, add_a, rem_a = set(st.modified), set(st.added), set(st.removed) |
413 mod_a, add_a, rem_a = set(st.modified), set(st.added), set(st.removed) |
414 if do3way: |
414 if do3way: |
415 stb = repo.status(node1b, node2, matcher, listsubrepos=subrepos) |
415 stb = ctx1b.status(ctx2, matcher, listsubrepos=subrepos) |
416 mod_b, add_b, rem_b = ( |
416 mod_b, add_b, rem_b = ( |
417 set(stb.modified), |
417 set(stb.modified), |
418 set(stb.added), |
418 set(stb.added), |
419 set(stb.removed), |
419 set(stb.removed), |
420 ) |
420 ) |
423 modadd = mod_a | add_a | mod_b | add_b |
423 modadd = mod_a | add_a | mod_b | add_b |
424 common = modadd | rem_a | rem_b |
424 common = modadd | rem_a | rem_b |
425 if not common: |
425 if not common: |
426 return 0 |
426 return 0 |
427 |
427 |
428 # Always make a copy of node1a (and node1b, if applicable) |
428 # Always make a copy of ctx1a (and ctx1b, if applicable) |
429 # dir1a should contain files which are: |
429 # dir1a should contain files which are: |
430 # * modified or removed from node1a to node2 |
430 # * modified or removed from ctx1a to ctx2 |
431 # * modified or added from node1b to node2 |
431 # * modified or added from ctx1b to ctx2 |
432 # (except file added from node1a to node2 as they were not present in |
432 # (except file added from ctx1a to ctx2 as they were not present in |
433 # node1a) |
433 # ctx1a) |
434 dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) |
434 dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) |
435 dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[0] |
435 dir1a = snapshot(ui, repo, dir1a_files, ctx1a.node(), tmproot, subrepos)[0] |
436 rev1a = b'@%d' % repo[node1a].rev() |
436 rev1a = b'@%d' % ctx1a.rev() |
437 if do3way: |
437 if do3way: |
438 # file calculation criteria same as dir1a |
438 # file calculation criteria same as dir1a |
439 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) |
439 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b) |
440 dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot, subrepos)[0] |
440 dir1b = snapshot( |
441 rev1b = b'@%d' % repo[node1b].rev() |
441 ui, repo, dir1b_files, ctx1b.node(), tmproot, subrepos |
|
442 )[0] |
|
443 rev1b = b'@%d' % ctx1b.rev() |
442 else: |
444 else: |
443 dir1b = None |
445 dir1b = None |
444 rev1b = b'' |
446 rev1b = b'' |
445 |
447 |
446 fnsandstat = [] |
448 fnsandstat = [] |
447 |
449 |
448 # If node2 in not the wc or there is >1 change, copy it |
450 # If ctx2 is not the wc or there is >1 change, copy it |
449 dir2root = b'' |
451 dir2root = b'' |
450 rev2 = b'' |
452 rev2 = b'' |
451 if node2: |
453 if ctx2.node() is not None: |
452 dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0] |
454 dir2 = snapshot(ui, repo, modadd, ctx2.node(), tmproot, subrepos)[0] |
453 rev2 = b'@%d' % repo[node2].rev() |
455 rev2 = b'@%d' % ctx2.rev() |
454 elif len(common) > 1: |
456 elif len(common) > 1: |
455 # we only actually need to get the files to copy back to |
457 # we only actually need to get the files to copy back to |
456 # the working dir in this case (because the other cases |
458 # the working dir in this case (because the other cases |
457 # are: diffing 2 revisions or single file -- in which case |
459 # are: diffing 2 revisions or single file -- in which case |
458 # the file is already directly passed to the diff tool). |
460 # the file is already directly passed to the diff tool). |
561 if not revs: |
563 if not revs: |
562 ctx1b = repo[None].p2() |
564 ctx1b = repo[None].p2() |
563 else: |
565 else: |
564 ctx1b = repo[nullid] |
566 ctx1b = repo[nullid] |
565 |
567 |
566 node1a = ctx1a.node() |
|
567 node1b = ctx1b.node() |
|
568 node2 = ctx2.node() |
|
569 |
|
570 # Disable 3-way merge if there is only one parent |
568 # Disable 3-way merge if there is only one parent |
571 if do3way: |
569 if do3way: |
572 if node1b == nullid: |
570 if ctx1b.node() == nullid: |
573 do3way = False |
571 do3way = False |
574 |
572 |
575 matcher = scmutil.match(repo[node2], pats, opts) |
573 matcher = scmutil.match(ctx2, pats, opts) |
576 |
574 |
577 if opts.get(b'patch'): |
575 if opts.get(b'patch'): |
578 if opts.get(b'subrepos'): |
576 if opts.get(b'subrepos'): |
579 raise error.Abort(_(b'--patch cannot be used with --subrepos')) |
577 raise error.Abort(_(b'--patch cannot be used with --subrepos')) |
580 if opts.get(b'per_file'): |
578 if opts.get(b'per_file'): |
581 raise error.Abort(_(b'--patch cannot be used with --per-file')) |
579 raise error.Abort(_(b'--patch cannot be used with --per-file')) |
582 if node2 is None: |
580 if ctx2.node() is None: |
583 raise error.Abort(_(b'--patch requires two revisions')) |
581 raise error.Abort(_(b'--patch requires two revisions')) |
584 |
582 |
585 tmproot = pycompat.mkdtemp(prefix=b'extdiff.') |
583 tmproot = pycompat.mkdtemp(prefix=b'extdiff.') |
586 try: |
584 try: |
587 if opts.get(b'patch'): |
585 if opts.get(b'patch'): |
588 return diffpatch(ui, repo, node1a, node2, tmproot, matcher, cmdline) |
586 return diffpatch( |
|
587 ui, repo, ctx1a.node(), ctx2.node(), tmproot, matcher, cmdline |
|
588 ) |
589 |
589 |
590 return diffrevs( |
590 return diffrevs( |
591 ui, |
591 ui, |
592 repo, |
592 repo, |
593 node1a, |
593 ctx1a, |
594 node1b, |
594 ctx1b, |
595 node2, |
595 ctx2, |
596 matcher, |
596 matcher, |
597 tmproot, |
597 tmproot, |
598 cmdline, |
598 cmdline, |
599 do3way, |
599 do3way, |
600 guitool, |
600 guitool, |