changeset 280:a9d08cf9a44f

Handle new files that are coming from merged codelines
author Franz Glasner <hg@dom66.de>
date Sun, 06 Jan 2019 15:19:28 +0100
parents fd0f5631d11a
children ee524547e57d
files extensions/timestamps.py tests/test-timestamps.t
diffstat 2 files changed, 59 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/extensions/timestamps.py	Sat Jan 05 17:04:50 2019 +0100
+++ b/extensions/timestamps.py	Sun Jan 06 15:19:28 2019 +0100
@@ -91,6 +91,7 @@
 
 
 _noobj = object()
+_conflictobj = object()
 
 cmdtable = {}
 
@@ -254,7 +255,7 @@
     ts = Timestamps.from_filename(ui, name=repo.wjoin(TIMESTAMPS_DATABASE))
     if ts is None:
         raise error.Abort(_("timestamps database file does not exist"))
-    _restore_timestamps(repo, ctx, matcher, ts)
+    _restore_timestamps(repo, ctx, matcher, ts, ui=ui)
 
 
 def show_timestamps(ui, repo, ctx, fm,
@@ -504,6 +505,8 @@
                     # a "> merge rev" block is the last marker of a merge block
                     if mergeblock_type == '>':
                         mergeblock_type = ''
+                        assert not record
+                        assert not field
                 else:
                     # just a normal char
                     field.append(c)
@@ -714,27 +717,27 @@
                         "invalid absolute path in line %d" % lineno)
                 if mergeblock_type:
                     mdata[k] = v
-                    self._d[k] = None
+                    self._d[k] = _conflictobj
                 else:
                     self._d[k] = v
                     datano += 1
             elif not record:
                 if mergeblock_type:
                     mdata["/-%d/" % lineno] = ''
-                    self._d["/-%d/" % lineno] = None
+                    self._d["/-%d/" % lineno] = _conflictobj
                 else:
                     self._d["/-%d/" % lineno] = ''
             elif len(record) == 1:
                 if record[0].startswith("#"):
                     if mergeblock_type:
                         mdata = record[0]
-                        self._d["/comment-%d" % lineno] = None
+                        self._d["/comment-%d" % lineno] = _conflictobj
                     else:
                         self._d["/comment-%d" % lineno] = record[0]
                 elif record[0].startswith("version="):
                     if mergeblock_type:
                         mdata["/version/"] = int(record[0][8:], 10)
-                        self._d["/version/"] = None
+                        self._d["/version/"] = _conflictobj
                     else:
                         if self._version is None:
                             self._d["/version/"] = self._version = \
@@ -749,7 +752,7 @@
                 elif record[0].startswith("encoding="):
                     if mergeblock_type:
                         mdata["/encoding/"] = record[0][9:]
-                        self._d["/encoding/"] = None
+                        self._d["/encoding/"] = _conflictobj
                     else:
                         if self._version is None:
                             raise ValueError("no version record given yet")
@@ -832,6 +835,24 @@
                 v = default
         return v
 
+    def getone(self, key, default=None, ui=None):
+        hits = 0
+        v = _noobj
+        for d in (self._base, self._other, self._local, self._d):
+            tmp = d.get(key, _noobj)
+            if (tmp is not _noobj) and (tmp is not _conflictobj):
+                hits += 1
+                v = tmp
+        if hits > 1:
+            if ui:
+                ui.warn(_("file `%s' is not unique in the timestamps database\n") % key)
+            return default
+        if v is _noobj:
+            assert hits == 0
+            return default
+        else:
+            return v
+
     def __delitem__(self, key):
         del self._d[key]
 
@@ -888,7 +909,17 @@
             # the same as in revert's implementation in `cmdutil.revert`
             patterns = scmutil.match(wctx, kwds.get("pats"), opts=opts)
             candidates = wctx.walk(patterns)
-        _restore_timestamps(repo, candidates, matcher, ts)
+        _restore_timestamps(repo, candidates, matcher, ts, ui=ui)
+    elif hooktype == "post-resolve":
+        wctx = repo[None]
+        matcher = gen_matcher(repo, wctx)
+        if matcher is None:
+            return
+        ts = Timestamps.from_filename(ui, name=repo.wjoin(TIMESTAMPS_DATABASE))
+        if ts is None:
+            ui.warn(_("update.timestamps: timestamps database file could not be found or read\n"))
+            return
+        ui.note(_("restoring timestamps\n"))
 
 
 def update_hook(ui, repo, hooktype, **kwds):
@@ -1053,11 +1084,12 @@
                     if not parent2:
                         self._ts_update_update(tsmatch, ts)
                     else:
-                        self._ts_update_merge(tsmatch, ts)
+                        self._ts_update_update(tsmatch, ts,
+                                               allow_other_region=True)
             else:
                 self.ui.debug("update.timestamps: timestamps not activated/configured\n")
 
-        def _ts_update_update(self, tsmatch, ts):
+        def _ts_update_update(self, tsmatch, ts, allow_other_region=False):
             """:hg:`update`, :hg:`merge --abort`"""
             to_update = set()
             for p in self.__from_parents:
@@ -1077,12 +1109,8 @@
             if _DEV:
                 self.ui.debug("UPDATE TO_UPDATE w/o resolved: "
                               + repr(to_update) + '\n')
-            _restore_timestamps(self, to_update, tsmatch, ts)
-
-        def _ts_update_merge(self, tsmatch, ts):
-            """:hg:`merge`"""
-            # XXX TBD
-            self._ts_update_update(tsmatch, ts)
+            _restore_timestamps(self, to_update, tsmatch, ts,
+                                allow_other_region=allow_other_region)
 
     repo.__class__ = TimestampedRepo
 
@@ -1098,28 +1126,37 @@
     ui.setconfig('hooks', 'post-revert.timestamps', post_hook)
 
 
-def _restore_timestamps(repo, candidates, tsmatch, tsdb, alt=None):
+def _restore_timestamps(repo, candidates, tsmatch, tsdb,
+                        ui=None,
+                        alt=None,
+                        allow_other_region=False):
     """Restore file timestamps of files in iterable `candidates` that
     match `tsmatch` to the times in database `tsdb`.
     If `alt` is given and one of "base", "local", "other" try to find a
     timestamp value from this merge conflict region if there is one.
+    If `allow_other_region` is true then a timestamp value is allowed to be
+    found in any of a merge conflict region also.
 
     """
     if not repo.local():
         raise error.Abort(_("repository is not local"))
+    ui = ui or repo.ui
     with FloatTimesInStat():
         for f in candidates:
             if tsmatch(f):
-                mtime = tsdb.getalt(f, alt)
+                if allow_other_region:
+                    mtime = tsdb.getone(f, ui=ui)
+                else:
+                    mtime = tsdb.getalt(f, alt)
                 if mtime is not None:
                     mt = calendar.timegm(dt_from_isoformat(mtime).timetuple())
                     if _DEV:
-                        repo.ui.debug("RESTORING TIMESTAMP: " + f + ' -> '
-                                      + mtime + '\n')
+                        ui.debug("RESTORING TIMESTAMP: " + f + ' -> '
+                                 + mtime + '\n')
                     try:
                         os.utime(repo.wjoin(f), (time.time(), mt))
                     except IOError:
-                        repo.ui.warn(_("cannot set mtime for file: %s") % f)
+                        ui.warn(_("cannot set mtime for file: %s") % f)
 
 
 def _debug_mergestate(ui, ms):
--- a/tests/test-timestamps.t	Sat Jan 05 17:04:50 2019 +0100
+++ b/tests/test-timestamps.t	Sun Jan 06 15:19:28 2019 +0100
@@ -196,6 +196,7 @@
   $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T02:03:04Z files/test1.txt
   $ "$TSPY" "$TESTDIR/lib-stat.py" --differs=2017-12-01T08:09:10Z files/test2.txt
   $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T05:06:07Z files/test3.txt
+  $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T06:07:08Z files/test4-2.txt
 
 Abort the merge for now
 
@@ -248,5 +249,6 @@
   $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T02:03:04Z files/test1.txt
   $ "$TSPY" "$TESTDIR/lib-stat.py" --differs=2017-12-01T08:09:10Z files/test2.txt
   $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T05:06:07Z files/test3.txt
+  $ "$TSPY" "$TESTDIR/lib-stat.py" --check=2017-12-01T06:07:08Z files/test4-2.txt
 
   $ cd ..