mercurial/commands.py
changeset 14611 adbf5e7df96d
parent 14610 5d6244930559
child 14631 234b9795d74e
equal deleted inserted replaced
14610:5d6244930559 14611:adbf5e7df96d
  3000        'meaning as the corresponding patch option'), _('NUM')),
  3000        'meaning as the corresponding patch option'), _('NUM')),
  3001     ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
  3001     ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
  3002     ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
  3002     ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
  3003     ('', 'no-commit', None,
  3003     ('', 'no-commit', None,
  3004      _("don't commit, just update the working directory")),
  3004      _("don't commit, just update the working directory")),
       
  3005     ('', 'bypass', None,
       
  3006      _("apply patch without touching the working directory")),
  3005     ('', 'exact', None,
  3007     ('', 'exact', None,
  3006      _('apply patch to the nodes from which it was generated')),
  3008      _('apply patch to the nodes from which it was generated')),
  3007     ('', 'import-branch', None,
  3009     ('', 'import-branch', None,
  3008      _('use any branch information in patch (implied by --exact)'))] +
  3010      _('use any branch information in patch (implied by --exact)'))] +
  3009     commitopts + commitopts2 + similarityopts,
  3011     commitopts + commitopts2 + similarityopts,
  3033     the parent of each patch before applying it, and will abort if the
  3035     the parent of each patch before applying it, and will abort if the
  3034     resulting changeset has a different ID than the one recorded in
  3036     resulting changeset has a different ID than the one recorded in
  3035     the patch. This may happen due to character set problems or other
  3037     the patch. This may happen due to character set problems or other
  3036     deficiencies in the text patch format.
  3038     deficiencies in the text patch format.
  3037 
  3039 
       
  3040     Use --bypass to apply and commit patches directly to the
       
  3041     repository, not touching the working directory. Without --exact,
       
  3042     patches will be applied on top of the working directory parent
       
  3043     revision.
       
  3044 
  3038     With -s/--similarity, hg will attempt to discover renames and
  3045     With -s/--similarity, hg will attempt to discover renames and
  3039     copies in the patch in the same way as 'addremove'.
  3046     copies in the patch in the same way as 'addremove'.
  3040 
  3047 
  3041     To read a patch from standard input, use "-" as the patch name. If
  3048     To read a patch from standard input, use "-" as the patch name. If
  3042     a URL is specified, the patch will be downloaded from it.
  3049     a URL is specified, the patch will be downloaded from it.
  3048 
  3055 
  3049     date = opts.get('date')
  3056     date = opts.get('date')
  3050     if date:
  3057     if date:
  3051         opts['date'] = util.parsedate(date)
  3058         opts['date'] = util.parsedate(date)
  3052 
  3059 
       
  3060     update = not opts.get('bypass')
       
  3061     if not update and opts.get('no_commit'):
       
  3062         raise util.Abort(_('cannot use --no-commit with --bypass'))
  3053     try:
  3063     try:
  3054         sim = float(opts.get('similarity') or 0)
  3064         sim = float(opts.get('similarity') or 0)
  3055     except ValueError:
  3065     except ValueError:
  3056         raise util.Abort(_('similarity must be a number'))
  3066         raise util.Abort(_('similarity must be a number'))
  3057     if sim < 0 or sim > 100:
  3067     if sim < 0 or sim > 100:
  3058         raise util.Abort(_('similarity must be between 0 and 100'))
  3068         raise util.Abort(_('similarity must be between 0 and 100'))
  3059 
  3069     if sim and not update:
  3060     if opts.get('exact') or not opts.get('force'):
  3070         raise util.Abort(_('cannot use --similarity with --bypass'))
       
  3071 
       
  3072     if (opts.get('exact') or not opts.get('force')) and update:
  3061         cmdutil.bailifchanged(repo)
  3073         cmdutil.bailifchanged(repo)
  3062 
  3074 
  3063     d = opts["base"]
  3075     d = opts["base"]
  3064     strip = opts["strip"]
  3076     strip = opts["strip"]
  3065     wlock = lock = None
  3077     wlock = lock = None
  3066     msgs = []
  3078     msgs = []
  3067 
  3079 
  3068     def tryone(ui, hunk):
  3080     def checkexact(repo, n, nodeid):
       
  3081         if opts.get('exact') and hex(n) != nodeid:
       
  3082             repo.rollback()
       
  3083             raise util.Abort(_('patch is damaged or loses information'))
       
  3084 
       
  3085     def tryone(ui, hunk, parents):
  3069         tmpname, message, user, date, branch, nodeid, p1, p2 = \
  3086         tmpname, message, user, date, branch, nodeid, p1, p2 = \
  3070             patch.extract(ui, hunk)
  3087             patch.extract(ui, hunk)
  3071 
  3088 
  3072         if not tmpname:
  3089         if not tmpname:
  3073             return None
  3090             return None
  3084             else:
  3101             else:
  3085                 # launch the editor
  3102                 # launch the editor
  3086                 message = None
  3103                 message = None
  3087             ui.debug('message:\n%s\n' % message)
  3104             ui.debug('message:\n%s\n' % message)
  3088 
  3105 
  3089             wp = repo.parents()
  3106             if len(parents) == 1:
  3090             if len(wp) == 1:
  3107                 parents.append(repo[nullid])
  3091                 wp.append(repo[nullid])
       
  3092             if opts.get('exact'):
  3108             if opts.get('exact'):
  3093                 if not nodeid or not p1:
  3109                 if not nodeid or not p1:
  3094                     raise util.Abort(_('not a Mercurial patch'))
  3110                     raise util.Abort(_('not a Mercurial patch'))
  3095                 p1 = repo[p1]
  3111                 p1 = repo[p1]
  3096                 p2 = repo[p2 or nullid]
  3112                 p2 = repo[p2 or nullid]
  3097             elif p2:
  3113             elif p2:
  3098                 try:
  3114                 try:
  3099                     p1 = repo[p1]
  3115                     p1 = repo[p1]
  3100                     p2 = repo[p2]
  3116                     p2 = repo[p2]
  3101                 except error.RepoError:
  3117                 except error.RepoError:
  3102                     p1, p2 = wp
  3118                     p1, p2 = parents
  3103             else:
  3119             else:
  3104                 p1, p2 = wp
  3120                 p1, p2 = parents
  3105 
  3121 
  3106             if opts.get('exact') and p1 != wp[0]:
  3122             n = None
  3107                 hg.clean(repo, p1.node())
  3123             if update:
  3108             if p1 != wp[0] and p2 != wp[1]:
  3124                 if opts.get('exact') and p1 != parents[0]:
  3109                 repo.dirstate.setparents(p1.node(), p2.node())
  3125                     hg.clean(repo, p1.node())
  3110 
  3126                 if p1 != parents[0] and p2 != parents[1]:
  3111             if opts.get('exact') or opts.get('import_branch'):
  3127                     repo.dirstate.setparents(p1.node(), p2.node())
  3112                 repo.dirstate.setbranch(branch or 'default')
  3128 
  3113 
  3129                 if opts.get('exact') or opts.get('import_branch'):
  3114             files = set()
  3130                     repo.dirstate.setbranch(branch or 'default')
  3115             patch.patch(ui, repo, tmpname, strip=strip, files=files,
  3131 
  3116                         eolmode=None, similarity=sim / 100.0)
  3132                 files = set()
  3117             files = list(files)
  3133                 patch.patch(ui, repo, tmpname, strip=strip, files=files,
  3118             if opts.get('no_commit'):
  3134                             eolmode=None, similarity=sim / 100.0)
  3119                 if message:
  3135                 files = list(files)
  3120                     msgs.append(message)
  3136                 if opts.get('no_commit'):
       
  3137                     if message:
       
  3138                         msgs.append(message)
       
  3139                 else:
       
  3140                     if opts.get('exact'):
       
  3141                         m = None
       
  3142                     else:
       
  3143                         m = scmutil.matchfiles(repo, files or [])
       
  3144                     n = repo.commit(message, opts.get('user') or user,
       
  3145                                     opts.get('date') or date, match=m,
       
  3146                                     editor=cmdutil.commiteditor)
       
  3147                     checkexact(repo, n, nodeid)
       
  3148                     # Force a dirstate write so that the next transaction
       
  3149                     # backups an up-to-date file.
       
  3150                     repo.dirstate.write()
  3121             else:
  3151             else:
  3122                 if opts.get('exact'):
  3152                 if opts.get('exact') or opts.get('import_branch'):
  3123                     m = None
  3153                     branch = branch or 'default'
  3124                 else:
  3154                 else:
  3125                     m = scmutil.matchfiles(repo, files or [])
  3155                     branch = p1.branch()
  3126                 n = repo.commit(message, opts.get('user') or user,
  3156                 store = patch.filestore()
  3127                                 opts.get('date') or date, match=m,
  3157                 try:
  3128                                 editor=cmdutil.commiteditor)
  3158                     files = set()
  3129                 if opts.get('exact'):
  3159                     try:
  3130                     if hex(n) != nodeid:
  3160                         patch.patchrepo(ui, repo, p1, store, tmpname, strip,
  3131                         repo.rollback()
  3161                                         files, eolmode=None)
  3132                         raise util.Abort(_('patch is damaged'
  3162                     except patch.PatchError, e:
  3133                                            ' or loses information'))
  3163                         raise util.Abort(str(e))
  3134                 # Force a dirstate write so that the next transaction
  3164                     memctx = patch.makememctx(repo, (p1.node(), p2.node()),
  3135                 # backups an up-do-date file.
  3165                                               message,
  3136                 repo.dirstate.write()
  3166                                               opts.get('user') or user,
  3137                 if n:
  3167                                               opts.get('date') or date,
  3138                     commitid = short(n)
  3168                                               branch, files, store,
  3139 
  3169                                               editor=cmdutil.commiteditor)
       
  3170                     repo.savecommitmessage(memctx.description())
       
  3171                     n = memctx.commit()
       
  3172                     checkexact(repo, n, nodeid)
       
  3173                 finally:
       
  3174                     store.close()
       
  3175             if n:
       
  3176                 commitid = short(n)
  3140             return commitid
  3177             return commitid
  3141         finally:
  3178         finally:
  3142             os.unlink(tmpname)
  3179             os.unlink(tmpname)
  3143 
  3180 
  3144     try:
  3181     try:
  3145         wlock = repo.wlock()
  3182         wlock = repo.wlock()
  3146         lock = repo.lock()
  3183         lock = repo.lock()
       
  3184         parents = repo.parents()
  3147         lastcommit = None
  3185         lastcommit = None
  3148         for p in patches:
  3186         for p in patches:
  3149             pf = os.path.join(d, p)
  3187             pf = os.path.join(d, p)
  3150 
  3188 
  3151             if pf == '-':
  3189             if pf == '-':
  3155                 ui.status(_("applying %s\n") % p)
  3193                 ui.status(_("applying %s\n") % p)
  3156                 pf = url.open(ui, pf)
  3194                 pf = url.open(ui, pf)
  3157 
  3195 
  3158             haspatch = False
  3196             haspatch = False
  3159             for hunk in patch.split(pf):
  3197             for hunk in patch.split(pf):
  3160                 commitid = tryone(ui, hunk)
  3198                 commitid = tryone(ui, hunk, parents)
  3161                 if commitid:
  3199                 if commitid:
  3162                     haspatch = True
  3200                     haspatch = True
  3163                     if lastcommit:
  3201                     if lastcommit:
  3164                         ui.status(_('applied %s\n') % lastcommit)
  3202                         ui.status(_('applied %s\n') % lastcommit)
  3165                     lastcommit = commitid
  3203                     lastcommit = commitid
       
  3204                 if update or opts.get('exact'):
       
  3205                     parents = repo.parents()
       
  3206                 else:
       
  3207                     parents = [repo[commitid]]
  3166 
  3208 
  3167             if not haspatch:
  3209             if not haspatch:
  3168                 raise util.Abort(_('no diffs found'))
  3210                 raise util.Abort(_('no diffs found'))
  3169 
  3211 
  3170         if msgs:
  3212         if msgs: