hgext/extdiff.py
changeset 45126 48c38018bd77
parent 44867 8e8fd938ca07
child 45127 da2e69a278df
equal deleted inserted replaced
45125:f55099982bc5 45126:48c38018bd77
   348         with ui.timeblockedsection(b'extdiff'):
   348         with ui.timeblockedsection(b'extdiff'):
   349             for proc in waitprocs:
   349             for proc in waitprocs:
   350                 proc.wait()
   350                 proc.wait()
   351 
   351 
   352 
   352 
       
   353 def diffpatch(ui, repo, node1a, node2, tmproot, matcher, cmdline, do3way):
       
   354     template = b'hg-%h.patch'
       
   355     with formatter.nullformatter(ui, b'extdiff', {}) as fm:
       
   356         cmdutil.export(
       
   357             repo,
       
   358             [repo[node1a].rev(), repo[node2].rev()],
       
   359             fm,
       
   360             fntemplate=repo.vfs.reljoin(tmproot, template),
       
   361             match=matcher,
       
   362         )
       
   363     label1a = cmdutil.makefilename(repo[node1a], template)
       
   364     label2 = cmdutil.makefilename(repo[node2], template)
       
   365     dir1a = repo.vfs.reljoin(tmproot, label1a)
       
   366     dir2 = repo.vfs.reljoin(tmproot, label2)
       
   367     dir1b = None
       
   368     label1b = None
       
   369     cmdline = formatcmdline(
       
   370         cmdline,
       
   371         repo.root,
       
   372         do3way=do3way,
       
   373         parent1=dir1a,
       
   374         plabel1=label1a,
       
   375         parent2=dir1b,
       
   376         plabel2=label1b,
       
   377         child=dir2,
       
   378         clabel=label2,
       
   379     )
       
   380     ui.debug(b'running %r in %s\n' % (pycompat.bytestr(cmdline), tmproot))
       
   381     ui.system(cmdline, cwd=tmproot, blockedtag=b'extdiff')
       
   382     return 1
       
   383 
       
   384 
   353 def dodiff(ui, repo, cmdline, pats, opts, guitool=False):
   385 def dodiff(ui, repo, cmdline, pats, opts, guitool=False):
   354     '''Do the actual diff:
   386     '''Do the actual diff:
   355 
   387 
   356     - copy to a temp structure if diffing 2 internal revisions
   388     - copy to a temp structure if diffing 2 internal revisions
   357     - copy to a temp structure if diffing working revision with
   389     - copy to a temp structure if diffing working revision with
   414         if not common:
   446         if not common:
   415             return 0
   447             return 0
   416 
   448 
   417     tmproot = pycompat.mkdtemp(prefix=b'extdiff.')
   449     tmproot = pycompat.mkdtemp(prefix=b'extdiff.')
   418     try:
   450     try:
   419         if not opts.get(b'patch'):
   451         if opts.get(b'patch'):
   420             # Always make a copy of node1a (and node1b, if applicable)
   452             return diffpatch(
   421             dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
   453                 ui, repo, node1a, node2, tmproot, matcher, cmdline, do3way
   422             dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[
   454             )
       
   455 
       
   456         # Always make a copy of node1a (and node1b, if applicable)
       
   457         dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
       
   458         dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot, subrepos)[0]
       
   459         rev1a = b'@%d' % repo[node1a].rev()
       
   460         if do3way:
       
   461             dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
       
   462             dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot, subrepos)[
   423                 0
   463                 0
   424             ]
   464             ]
   425             rev1a = b'@%d' % repo[node1a].rev()
   465             rev1b = b'@%d' % repo[node1b].rev()
       
   466         else:
       
   467             dir1b = None
       
   468             rev1b = b''
       
   469 
       
   470         fnsandstat = []
       
   471 
       
   472         # If node2 in not the wc or there is >1 change, copy it
       
   473         dir2root = b''
       
   474         rev2 = b''
       
   475         if node2:
       
   476             dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0]
       
   477             rev2 = b'@%d' % repo[node2].rev()
       
   478         elif len(common) > 1:
       
   479             # we only actually need to get the files to copy back to
       
   480             # the working dir in this case (because the other cases
       
   481             # are: diffing 2 revisions or single file -- in which case
       
   482             # the file is already directly passed to the diff tool).
       
   483             dir2, fnsandstat = snapshot(
       
   484                 ui, repo, modadd, None, tmproot, subrepos
       
   485             )
       
   486         else:
       
   487             # This lets the diff tool open the changed file directly
       
   488             dir2 = b''
       
   489             dir2root = repo.root
       
   490 
       
   491         label1a = rev1a
       
   492         label1b = rev1b
       
   493         label2 = rev2
       
   494 
       
   495         # If only one change, diff the files instead of the directories
       
   496         # Handle bogus modifies correctly by checking if the files exist
       
   497         if len(common) == 1:
       
   498             common_file = util.localpath(common.pop())
       
   499             dir1a = os.path.join(tmproot, dir1a, common_file)
       
   500             label1a = common_file + rev1a
       
   501             if not os.path.isfile(dir1a):
       
   502                 dir1a = pycompat.osdevnull
   426             if do3way:
   503             if do3way:
   427                 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
   504                 dir1b = os.path.join(tmproot, dir1b, common_file)
   428                 dir1b = snapshot(
   505                 label1b = common_file + rev1b
   429                     ui, repo, dir1b_files, node1b, tmproot, subrepos
   506                 if not os.path.isfile(dir1b):
   430                 )[0]
   507                     dir1b = pycompat.osdevnull
   431                 rev1b = b'@%d' % repo[node1b].rev()
   508             dir2 = os.path.join(dir2root, dir2, common_file)
   432             else:
   509             label2 = common_file + rev2
   433                 dir1b = None
       
   434                 rev1b = b''
       
   435 
       
   436             fnsandstat = []
       
   437 
       
   438             # If node2 in not the wc or there is >1 change, copy it
       
   439             dir2root = b''
       
   440             rev2 = b''
       
   441             if node2:
       
   442                 dir2 = snapshot(ui, repo, modadd, node2, tmproot, subrepos)[0]
       
   443                 rev2 = b'@%d' % repo[node2].rev()
       
   444             elif len(common) > 1:
       
   445                 # we only actually need to get the files to copy back to
       
   446                 # the working dir in this case (because the other cases
       
   447                 # are: diffing 2 revisions or single file -- in which case
       
   448                 # the file is already directly passed to the diff tool).
       
   449                 dir2, fnsandstat = snapshot(
       
   450                     ui, repo, modadd, None, tmproot, subrepos
       
   451                 )
       
   452             else:
       
   453                 # This lets the diff tool open the changed file directly
       
   454                 dir2 = b''
       
   455                 dir2root = repo.root
       
   456 
       
   457             label1a = rev1a
       
   458             label1b = rev1b
       
   459             label2 = rev2
       
   460 
       
   461             # If only one change, diff the files instead of the directories
       
   462             # Handle bogus modifies correctly by checking if the files exist
       
   463             if len(common) == 1:
       
   464                 common_file = util.localpath(common.pop())
       
   465                 dir1a = os.path.join(tmproot, dir1a, common_file)
       
   466                 label1a = common_file + rev1a
       
   467                 if not os.path.isfile(dir1a):
       
   468                     dir1a = pycompat.osdevnull
       
   469                 if do3way:
       
   470                     dir1b = os.path.join(tmproot, dir1b, common_file)
       
   471                     label1b = common_file + rev1b
       
   472                     if not os.path.isfile(dir1b):
       
   473                         dir1b = pycompat.osdevnull
       
   474                 dir2 = os.path.join(dir2root, dir2, common_file)
       
   475                 label2 = common_file + rev2
       
   476         else:
       
   477             template = b'hg-%h.patch'
       
   478             with formatter.nullformatter(ui, b'extdiff', {}) as fm:
       
   479                 cmdutil.export(
       
   480                     repo,
       
   481                     [repo[node1a].rev(), repo[node2].rev()],
       
   482                     fm,
       
   483                     fntemplate=repo.vfs.reljoin(tmproot, template),
       
   484                     match=matcher,
       
   485                 )
       
   486             label1a = cmdutil.makefilename(repo[node1a], template)
       
   487             label2 = cmdutil.makefilename(repo[node2], template)
       
   488             dir1a = repo.vfs.reljoin(tmproot, label1a)
       
   489             dir2 = repo.vfs.reljoin(tmproot, label2)
       
   490             dir1b = None
       
   491             label1b = None
       
   492             fnsandstat = []
       
   493 
   510 
   494         if not perfile:
   511         if not perfile:
   495             # Run the external tool on the 2 temp directories or the patches
   512             # Run the external tool on the 2 temp directories or the patches
   496             cmdline = formatcmdline(
   513             cmdline = formatcmdline(
   497                 cmdline,
   514                 cmdline,