mercurial/patch.py
changeset 45098 20a65e397943
parent 45072 a56ba57c837d
child 45154 10f48720ef95
equal deleted inserted replaced
45097:dff208398ede 45098:20a65e397943
  2920                 ):
  2920                 ):
  2921                     continue
  2921                     continue
  2922         yield f1, f2, copyop
  2922         yield f1, f2, copyop
  2923 
  2923 
  2924 
  2924 
       
  2925 def _gitindex(text):
       
  2926     if not text:
       
  2927         text = b""
       
  2928     l = len(text)
       
  2929     s = hashutil.sha1(b'blob %d\0' % l)
       
  2930     s.update(text)
       
  2931     return hex(s.digest())
       
  2932 
       
  2933 
       
  2934 _gitmode = {b'l': b'120000', b'x': b'100755', b'': b'100644'}
       
  2935 
       
  2936 
  2925 def trydiff(
  2937 def trydiff(
  2926     repo,
  2938     repo,
  2927     revs,
  2939     revs,
  2928     ctx1,
  2940     ctx1,
  2929     ctx2,
  2941     ctx2,
  2942     losedatafn is not None, it will be called.
  2954     losedatafn is not None, it will be called.
  2943 
  2955 
  2944     pathfn is applied to every path in the diff output.
  2956     pathfn is applied to every path in the diff output.
  2945     '''
  2957     '''
  2946 
  2958 
  2947     def gitindex(text):
       
  2948         if not text:
       
  2949             text = b""
       
  2950         l = len(text)
       
  2951         s = hashutil.sha1(b'blob %d\0' % l)
       
  2952         s.update(text)
       
  2953         return hex(s.digest())
       
  2954 
       
  2955     if opts.noprefix:
  2959     if opts.noprefix:
  2956         aprefix = bprefix = b''
  2960         aprefix = bprefix = b''
  2957     else:
  2961     else:
  2958         aprefix = b'a/'
  2962         aprefix = b'a/'
  2959         bprefix = b'b/'
  2963         bprefix = b'b/'
  2965     def isempty(fctx):
  2969     def isempty(fctx):
  2966         return fctx is None or fctx.size() == 0
  2970         return fctx is None or fctx.size() == 0
  2967 
  2971 
  2968     date1 = dateutil.datestr(ctx1.date())
  2972     date1 = dateutil.datestr(ctx1.date())
  2969     date2 = dateutil.datestr(ctx2.date())
  2973     date2 = dateutil.datestr(ctx2.date())
  2970 
       
  2971     gitmode = {b'l': b'120000', b'x': b'100755', b'': b'100644'}
       
  2972 
  2974 
  2973     if not pathfn:
  2975     if not pathfn:
  2974         pathfn = lambda f: f
  2976         pathfn = lambda f: f
  2975 
  2977 
  2976     for f1, f2, copyop in _filepairs(modified, added, removed, copy, opts):
  2978     for f1, f2, copyop in _filepairs(modified, added, removed, copy, opts):
  3021         if opts.git:
  3023         if opts.git:
  3022             header.append(
  3024             header.append(
  3023                 b'diff --git %s%s %s%s' % (aprefix, path1, bprefix, path2)
  3025                 b'diff --git %s%s %s%s' % (aprefix, path1, bprefix, path2)
  3024             )
  3026             )
  3025             if not f1:  # added
  3027             if not f1:  # added
  3026                 header.append(b'new file mode %s' % gitmode[flag2])
  3028                 header.append(b'new file mode %s' % _gitmode[flag2])
  3027             elif not f2:  # removed
  3029             elif not f2:  # removed
  3028                 header.append(b'deleted file mode %s' % gitmode[flag1])
  3030                 header.append(b'deleted file mode %s' % _gitmode[flag1])
  3029             else:  # modified/copied/renamed
  3031             else:  # modified/copied/renamed
  3030                 mode1, mode2 = gitmode[flag1], gitmode[flag2]
  3032                 mode1, mode2 = _gitmode[flag1], _gitmode[flag2]
  3031                 if mode1 != mode2:
  3033                 if mode1 != mode2:
  3032                     header.append(b'old mode %s' % mode1)
  3034                     header.append(b'old mode %s' % mode1)
  3033                     header.append(b'new mode %s' % mode2)
  3035                     header.append(b'new mode %s' % mode2)
  3034                 if copyop is not None:
  3036                 if copyop is not None:
  3035                     if opts.showsimilarity:
  3037                     if opts.showsimilarity:
  3069             if fctx1 is not None:
  3071             if fctx1 is not None:
  3070                 content1 = fctx1.data()
  3072                 content1 = fctx1.data()
  3071             if fctx2 is not None:
  3073             if fctx2 is not None:
  3072                 content2 = fctx2.data()
  3074                 content2 = fctx2.data()
  3073 
  3075 
  3074         if binary and opts.git and not opts.nobinary:
  3076         data1 = (ctx1, fctx1, path1, flag1, content1, date1)
  3075             text = mdiff.b85diff(content1, content2)
  3077         data2 = (ctx2, fctx2, path2, flag2, content2, date2)
  3076             if text:
  3078         yield diffcontent(data1, data2, header, binary, opts)
  3077                 header.append(
  3079 
  3078                     b'index %s..%s' % (gitindex(content1), gitindex(content2))
  3080 
       
  3081 def diffcontent(data1, data2, header, binary, opts):
       
  3082     """ diffs two versions of a file.
       
  3083 
       
  3084     data1 and data2 are tuples containg:
       
  3085 
       
  3086         * ctx: changeset for the file
       
  3087         * fctx: file context for that file
       
  3088         * path1: name of the file
       
  3089         * flag: flags of the file
       
  3090         * content: full content of the file (can be null in case of binary)
       
  3091         * date: date of the changeset
       
  3092 
       
  3093     header: the patch header
       
  3094     binary: whether the any of the version of file is binary or not
       
  3095     opts:   user passed options
       
  3096 
       
  3097     It exists as a separate function so that extensions like extdiff can wrap
       
  3098     it and use the file content directly.
       
  3099     """
       
  3100 
       
  3101     ctx1, fctx1, path1, flag1, content1, date1 = data1
       
  3102     ctx2, fctx2, path2, flag2, content2, date2 = data2
       
  3103     if binary and opts.git and not opts.nobinary:
       
  3104         text = mdiff.b85diff(content1, content2)
       
  3105         if text:
       
  3106             header.append(
       
  3107                 b'index %s..%s' % (_gitindex(content1), _gitindex(content2))
       
  3108             )
       
  3109         hunks = ((None, [text]),)
       
  3110     else:
       
  3111         if opts.git and opts.index > 0:
       
  3112             flag = flag1
       
  3113             if flag is None:
       
  3114                 flag = flag2
       
  3115             header.append(
       
  3116                 b'index %s..%s %s'
       
  3117                 % (
       
  3118                     _gitindex(content1)[0 : opts.index],
       
  3119                     _gitindex(content2)[0 : opts.index],
       
  3120                     _gitmode[flag],
  3079                 )
  3121                 )
  3080             hunks = ((None, [text]),)
       
  3081         else:
       
  3082             if opts.git and opts.index > 0:
       
  3083                 flag = flag1
       
  3084                 if flag is None:
       
  3085                     flag = flag2
       
  3086                 header.append(
       
  3087                     b'index %s..%s %s'
       
  3088                     % (
       
  3089                         gitindex(content1)[0 : opts.index],
       
  3090                         gitindex(content2)[0 : opts.index],
       
  3091                         gitmode[flag],
       
  3092                     )
       
  3093                 )
       
  3094 
       
  3095             uheaders, hunks = mdiff.unidiff(
       
  3096                 content1,
       
  3097                 date1,
       
  3098                 content2,
       
  3099                 date2,
       
  3100                 path1,
       
  3101                 path2,
       
  3102                 binary=binary,
       
  3103                 opts=opts,
       
  3104             )
  3122             )
  3105             header.extend(uheaders)
  3123 
  3106         yield fctx1, fctx2, header, hunks
  3124         uheaders, hunks = mdiff.unidiff(
       
  3125             content1,
       
  3126             date1,
       
  3127             content2,
       
  3128             date2,
       
  3129             path1,
       
  3130             path2,
       
  3131             binary=binary,
       
  3132             opts=opts,
       
  3133         )
       
  3134         header.extend(uheaders)
       
  3135     return fctx1, fctx2, header, hunks
  3107 
  3136 
  3108 
  3137 
  3109 def diffstatsum(stats):
  3138 def diffstatsum(stats):
  3110     maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False
  3139     maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False
  3111     for f, a, r, b in stats:
  3140     for f, a, r, b in stats: