mercurial/localrepo.py
changeset 45240 ce9ee81df9ff
parent 45239 ae5c1a3bc339
child 45321 dc457177dbc1
equal deleted inserted replaced
45239:ae5c1a3bc339 45240:ce9ee81df9ff
  2769 
  2769 
  2770     def currentwlock(self):
  2770     def currentwlock(self):
  2771         """Returns the wlock if it's held, or None if it's not."""
  2771         """Returns the wlock if it's held, or None if it's not."""
  2772         return self._currentlock(self._wlockref)
  2772         return self._currentlock(self._wlockref)
  2773 
  2773 
  2774     def _filecommit(
       
  2775         self, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
       
  2776     ):
       
  2777         """
       
  2778         commit an individual file as part of a larger transaction
       
  2779 
       
  2780         input:
       
  2781 
       
  2782             fctx:       a file context with the content we are trying to commit
       
  2783             manifest1:  manifest of changeset first parent
       
  2784             manifest2:  manifest of changeset second parent
       
  2785             linkrev:    revision number of the changeset being created
       
  2786             tr:         current transation
       
  2787             individual: boolean, set to False to skip storing the copy data
       
  2788                         (only used by the Google specific feature of using
       
  2789                         changeset extra as copy source of truth).
       
  2790 
       
  2791         output: (filenode, touched)
       
  2792 
       
  2793             filenode: the filenode that should be used by this changeset
       
  2794             touched:  one of: None, 'added' or 'modified'
       
  2795         """
       
  2796 
       
  2797         fname = fctx.path()
       
  2798         fparent1 = manifest1.get(fname, nullid)
       
  2799         fparent2 = manifest2.get(fname, nullid)
       
  2800         touched = None
       
  2801         if fparent1 == fparent2 == nullid:
       
  2802             touched = 'added'
       
  2803 
       
  2804         if isinstance(fctx, context.filectx):
       
  2805             # This block fast path most comparisons which are usually done. It
       
  2806             # assumes that bare filectx is used and no merge happened, hence no
       
  2807             # need to create a new file revision in this case.
       
  2808             node = fctx.filenode()
       
  2809             if node in [fparent1, fparent2]:
       
  2810                 self.ui.debug(b'reusing %s filelog entry\n' % fname)
       
  2811                 if (
       
  2812                     fparent1 != nullid
       
  2813                     and manifest1.flags(fname) != fctx.flags()
       
  2814                 ) or (
       
  2815                     fparent2 != nullid
       
  2816                     and manifest2.flags(fname) != fctx.flags()
       
  2817                 ):
       
  2818                     touched = 'modified'
       
  2819                 return node, touched
       
  2820 
       
  2821         flog = self.file(fname)
       
  2822         meta = {}
       
  2823         cfname = fctx.copysource()
       
  2824         fnode = None
       
  2825 
       
  2826         if cfname and cfname != fname:
       
  2827             # Mark the new revision of this file as a copy of another
       
  2828             # file.  This copy data will effectively act as a parent
       
  2829             # of this new revision.  If this is a merge, the first
       
  2830             # parent will be the nullid (meaning "look up the copy data")
       
  2831             # and the second one will be the other parent.  For example:
       
  2832             #
       
  2833             # 0 --- 1 --- 3   rev1 changes file foo
       
  2834             #   \       /     rev2 renames foo to bar and changes it
       
  2835             #    \- 2 -/      rev3 should have bar with all changes and
       
  2836             #                      should record that bar descends from
       
  2837             #                      bar in rev2 and foo in rev1
       
  2838             #
       
  2839             # this allows this merge to succeed:
       
  2840             #
       
  2841             # 0 --- 1 --- 3   rev4 reverts the content change from rev2
       
  2842             #   \       /     merging rev3 and rev4 should use bar@rev2
       
  2843             #    \- 2 --- 4        as the merge base
       
  2844             #
       
  2845 
       
  2846             cnode = manifest1.get(cfname)
       
  2847             newfparent = fparent2
       
  2848 
       
  2849             if manifest2:  # branch merge
       
  2850                 if fparent2 == nullid or cnode is None:  # copied on remote side
       
  2851                     if cfname in manifest2:
       
  2852                         cnode = manifest2[cfname]
       
  2853                         newfparent = fparent1
       
  2854 
       
  2855             # Here, we used to search backwards through history to try to find
       
  2856             # where the file copy came from if the source of a copy was not in
       
  2857             # the parent directory. However, this doesn't actually make sense to
       
  2858             # do (what does a copy from something not in your working copy even
       
  2859             # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
       
  2860             # the user that copy information was dropped, so if they didn't
       
  2861             # expect this outcome it can be fixed, but this is the correct
       
  2862             # behavior in this circumstance.
       
  2863 
       
  2864             if cnode:
       
  2865                 self.ui.debug(
       
  2866                     b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode))
       
  2867                 )
       
  2868                 if includecopymeta:
       
  2869                     meta[b"copy"] = cfname
       
  2870                     meta[b"copyrev"] = hex(cnode)
       
  2871                 fparent1, fparent2 = nullid, newfparent
       
  2872             else:
       
  2873                 self.ui.warn(
       
  2874                     _(
       
  2875                         b"warning: can't find ancestor for '%s' "
       
  2876                         b"copied from '%s'!\n"
       
  2877                     )
       
  2878                     % (fname, cfname)
       
  2879                 )
       
  2880 
       
  2881         elif fparent1 == nullid:
       
  2882             fparent1, fparent2 = fparent2, nullid
       
  2883         elif fparent2 != nullid:
       
  2884             # is one parent an ancestor of the other?
       
  2885             fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
       
  2886             if fparent1 in fparentancestors:
       
  2887                 fparent1, fparent2 = fparent2, nullid
       
  2888             elif fparent2 in fparentancestors:
       
  2889                 fparent2 = nullid
       
  2890             elif not fparentancestors:
       
  2891                 # TODO: this whole if-else might be simplified much more
       
  2892                 ms = mergestatemod.mergestate.read(self)
       
  2893                 if (
       
  2894                     fname in ms
       
  2895                     and ms[fname] == mergestatemod.MERGE_RECORD_MERGED_OTHER
       
  2896                 ):
       
  2897                     fparent1, fparent2 = fparent2, nullid
       
  2898 
       
  2899         # is the file changed?
       
  2900         text = fctx.data()
       
  2901         if fparent2 != nullid or meta or flog.cmp(fparent1, text):
       
  2902             if touched is None:  # do not overwrite added
       
  2903                 touched = 'modified'
       
  2904             fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
       
  2905         # are just the flags changed during merge?
       
  2906         elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
       
  2907             touched = 'modified'
       
  2908             fnode = fparent1
       
  2909         else:
       
  2910             fnode = fparent1
       
  2911         return fnode, touched
       
  2912 
       
  2913     def checkcommitpatterns(self, wctx, match, status, fail):
  2774     def checkcommitpatterns(self, wctx, match, status, fail):
  2914         """check for commit arguments that aren't committable"""
  2775         """check for commit arguments that aren't committable"""
  2915         if match.isexact() or match.prefix():
  2776         if match.isexact() or match.prefix():
  2916             matched = set(status.modified + status.added + status.removed)
  2777             matched = set(status.modified + status.added + status.removed)
  2917 
  2778