mercurial/patch.py
changeset 2920 ef8ee4477019
parent 2907 b70740aefa4d
parent 2908 3848488244fc
child 2922 773c5b82d052
equal deleted inserted replaced
2907:b70740aefa4d 2920:ef8ee4477019
   213         raise
   213         raise
   214 
   214 
   215     tmpfp.close()
   215     tmpfp.close()
   216     return patchname
   216     return patchname
   217 
   217 
   218 def patch(patchname, ui, strip=1, cwd=None):
   218 def patch(strip, patchname, ui, cwd=None):
   219     """apply the patch <patchname> to the working directory.
   219     """apply the patch <patchname> to the working directory.
   220     a list of patched files is returned"""
   220     a list of patched files is returned"""
   221 
   221 
   222     (dopatch, gitpatches) = readgitpatch(patchname)
   222     (dopatch, gitpatches) = readgitpatch(patchname)
   223 
   223 
   224     files = {}
   224     files = {}
   225     fuzz = False
       
   226     if dopatch:
   225     if dopatch:
   227         if dopatch == 'filter':
   226         if dopatch == 'filter':
   228             patchname = dogitpatch(patchname, gitpatches)
   227             patchname = dogitpatch(patchname, gitpatches)
   229         patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
   228         patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch')
   230         args = []
   229         args = []
   236         if dopatch == 'filter':
   235         if dopatch == 'filter':
   237             False and os.unlink(patchname)
   236             False and os.unlink(patchname)
   238 
   237 
   239         for line in fp:
   238         for line in fp:
   240             line = line.rstrip()
   239             line = line.rstrip()
   241             ui.note(line + '\n')
   240             ui.status("%s\n" % line)
   242             if line.startswith('patching file '):
   241             if line.startswith('patching file '):
   243                 pf = util.parse_patch_output(line)
   242                 pf = util.parse_patch_output(line)
   244                 printed_file = False
       
   245                 files.setdefault(pf, (None, None))
   243                 files.setdefault(pf, (None, None))
   246             elif line.find('with fuzz') >= 0:
       
   247                 fuzz = True
       
   248                 if not printed_file:
       
   249                     ui.warn(pf + '\n')
       
   250                     printed_file = True
       
   251                 ui.warn(line + '\n')
       
   252             elif line.find('saving rejects to file') >= 0:
       
   253                 ui.warn(line + '\n')
       
   254             elif line.find('FAILED') >= 0:
       
   255                 if not printed_file:
       
   256                     ui.warn(pf + '\n')
       
   257                     printed_file = True
       
   258                 ui.warn(line + '\n')
       
   259             
       
   260         code = fp.close()
   244         code = fp.close()
   261         if code:
   245         if code:
   262             raise util.Abort(_("patch command failed: %s") %
   246             raise util.Abort(_("patch command failed: %s") %
   263                              util.explain_exit(code)[0])
   247                              util.explain_exit(code)[0])
   264 
   248 
   265     for gp in gitpatches:
   249     for gp in gitpatches:
   266         files[gp.path] = (gp.op, gp)
   250         files[gp.path] = (gp.op, gp)
   267 
   251 
   268     return (files, fuzz)
   252     return files
       
   253 
       
   254 def diffopts(ui, opts={}):
       
   255     return mdiff.diffopts(
       
   256         text=opts.get('text'),
       
   257         showfunc=(opts.get('show_function') or
       
   258                   ui.configbool('diff', 'showfunc', None)),
       
   259         ignorews=(opts.get('ignore_all_space') or
       
   260                   ui.configbool('diff', 'ignorews', None)),
       
   261         ignorewsamount=(opts.get('ignore_space_change') or
       
   262                         ui.configbool('diff', 'ignorewsamount', None)),
       
   263         ignoreblanklines=(opts.get('ignore_blank_lines') or
       
   264                           ui.configbool('diff', 'ignoreblanklines', None)))
   269 
   265 
   270 def diff(repo, node1=None, node2=None, files=None, match=util.always,
   266 def diff(repo, node1=None, node2=None, files=None, match=util.always,
   271          fp=None, changes=None, opts=None):
   267          fp=None, changes=None, opts=None):
   272     '''print diff of changes to files between two nodes, or node and
   268     '''print diff of changes to files between two nodes, or node and
   273     working directory.
   269     working directory.
   312         _date2 = util.datestr(change[2])
   308         _date2 = util.datestr(change[2])
   313         def date2(f):
   309         def date2(f):
   314             return _date2
   310             return _date2
   315         def read(f):
   311         def read(f):
   316             return repo.file(f).read(mmap2[f])
   312             return repo.file(f).read(mmap2[f])
   317         def renamed(f):
       
   318             src = repo.file(f).renamed(mmap2[f])
       
   319             return src and src[0] or None
       
   320     else:
   313     else:
   321         tz = util.makedate()[1]
   314         tz = util.makedate()[1]
   322         _date2 = util.datestr()
   315         _date2 = util.datestr()
   323         def date2(f):
   316         def date2(f):
   324             try:
   317             try:
   326             except OSError, err:
   319             except OSError, err:
   327                 if err.errno != errno.ENOENT: raise
   320                 if err.errno != errno.ENOENT: raise
   328                 return _date2
   321                 return _date2
   329         def read(f):
   322         def read(f):
   330             return repo.wread(f)
   323             return repo.wread(f)
   331         def renamed(f):
       
   332             return repo.dirstate.copies.get(f)
       
   333 
   324 
   334     if repo.ui.quiet:
   325     if repo.ui.quiet:
   335         r = None
   326         r = None
   336     else:
   327     else:
   337         hexfunc = repo.ui.verbose and hex or short
   328         hexfunc = repo.ui.verbose and hex or short
   338         r = [hexfunc(node) for node in [node1, node2] if node]
   329         r = [hexfunc(node) for node in [node1, node2] if node]
   339 
   330 
   340     if opts.git:
       
   341         copied = {}
       
   342         for f in added:
       
   343             src = renamed(f)
       
   344             if src:
       
   345                 copied[f] = src
       
   346         srcs = [x[1] for x in copied.items()]
       
   347 
       
   348     all = modified + added + removed
   331     all = modified + added + removed
   349     all.sort()
   332     all.sort()
   350     for f in all:
   333     for f in all:
   351         to = None
   334         to = None
   352         tn = None
   335         tn = None
   353         dodiff = True
       
   354         if f in mmap:
   336         if f in mmap:
   355             to = repo.file(f).read(mmap[f])
   337             to = repo.file(f).read(mmap[f])
   356         if f not in removed:
   338         if f not in removed:
   357             tn = read(f)
   339             tn = read(f)
   358         if opts.git:
   340         fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts))
   359             def gitmode(x):
       
   360                 return x and '100755' or '100644'
       
   361             def addmodehdr(header, omode, nmode):
       
   362                 if omode != nmode:
       
   363                     header.append('old mode %s\n' % omode)
       
   364                     header.append('new mode %s\n' % nmode)
       
   365 
       
   366             a, b = f, f
       
   367             header = []
       
   368             if f in added:
       
   369                 if node2:
       
   370                     mode = gitmode(mmap2.execf(f))
       
   371                 else:
       
   372                     mode = gitmode(util.is_exec(repo.wjoin(f), None))
       
   373                 if f in copied:
       
   374                     a = copied[f]
       
   375                     omode = gitmode(mmap.execf(a))
       
   376                     addmodehdr(header, omode, mode)
       
   377                     op = a in removed and 'rename' or 'copy'
       
   378                     header.append('%s from %s\n' % (op, a))
       
   379                     header.append('%s to %s\n' % (op, f))
       
   380                     to = repo.file(a).read(mmap[a])
       
   381                 else:
       
   382                     header.append('new file mode %s\n' % mode)
       
   383             elif f in removed:
       
   384                 if f in srcs:
       
   385                     dodiff = False
       
   386                 else:
       
   387                     mode = gitmode(mmap.execf(f))
       
   388                     header.append('deleted file mode %s\n' % mode)
       
   389             else:
       
   390                 omode = gitmode(mmap.execf(f))
       
   391                 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
       
   392                 addmodehdr(header, omode, nmode)
       
   393             r = None
       
   394             if dodiff:
       
   395                 header.insert(0, 'diff --git a/%s b/%s\n' % (a, b))
       
   396                 fp.write(''.join(header))
       
   397         if dodiff:
       
   398             fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, opts=opts))
       
   399 
   341 
   400 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
   342 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
   401            opts=None):
   343            opts=None):
   402     '''export changesets as hg patches.'''
   344     '''export changesets as hg patches.'''
   403 
   345