changeset 20070:509717d0d517 stable

merge with i18n
author Matt Mackall <mpm@selenic.com>
date Mon, 18 Nov 2013 15:43:45 -0500
parents 3d8bfe2ecf6d (diff) a7cb5ddb08de (current diff)
children 4778f398ec83
files
diffstat 12 files changed, 145 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/color.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/hgext/color.py	Mon Nov 18 15:43:45 2013 -0500
@@ -386,9 +386,7 @@
         # i18n: "label" is a keyword
         raise error.ParseError(_("label expects two arguments"))
 
-    thing = templater.stringify(args[1][0](context, mapping, args[1][1]))
-    thing = templater.runtemplate(context, mapping,
-                                  templater.compiletemplate(thing, context))
+    thing = templater._evalifliteral(args[1], context, mapping)
 
     # apparently, repo could be a string that is the favicon?
     repo = mapping.get('repo', '')
--- a/hgext/convert/subversion.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/hgext/convert/subversion.py	Mon Nov 18 15:43:45 2013 -0500
@@ -91,10 +91,11 @@
                   discover_changed_paths=True, strict_node_history=False):
     protocol = -1
     def receiver(orig_paths, revnum, author, date, message, pool):
+        paths = {}
         if orig_paths is not None:
             for k, v in orig_paths.iteritems():
-                orig_paths[k] = changedpath(v)
-        pickle.dump((orig_paths, revnum, author, date, message),
+                paths[k] = changedpath(v)
+        pickle.dump((paths, revnum, author, date, message),
                     fp, protocol)
 
     try:
--- a/hgext/largefiles/lfcommands.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/hgext/largefiles/lfcommands.py	Mon Nov 18 15:43:45 2013 -0500
@@ -438,91 +438,93 @@
         if filelist is not None:
             lfiles = [f for f in lfiles if f in filelist]
 
-        printed = False
-        if printmessage and lfiles:
-            ui.status(_('getting changed largefiles\n'))
-            printed = True
+        update = {}
+        updated, removed = 0, 0
+        for lfile in lfiles:
+            abslfile = repo.wjoin(lfile)
+            absstandin = repo.wjoin(lfutil.standin(lfile))
+            if os.path.exists(absstandin):
+                if (os.path.exists(absstandin + '.orig') and
+                    os.path.exists(abslfile)):
+                    shutil.copyfile(abslfile, abslfile + '.orig')
+                expecthash = lfutil.readstandin(repo, lfile)
+                if (expecthash != '' and
+                    (not os.path.exists(abslfile) or
+                     expecthash != lfutil.hashfile(abslfile))):
+                    if lfile not in repo[None]: # not switched to normal file
+                        util.unlinkpath(abslfile, ignoremissing=True)
+                    # use normallookup() to allocate entry in largefiles
+                    # dirstate, because lack of it misleads
+                    # lfilesrepo.status() into recognition that such cache
+                    # missing files are REMOVED.
+                    lfdirstate.normallookup(lfile)
+                    update[lfile] = expecthash
+            else:
+                # Remove lfiles for which the standin is deleted, unless the
+                # lfile is added to the repository again. This happens when a
+                # largefile is converted back to a normal file: the standin
+                # disappears, but a new (normal) file appears as the lfile.
+                if (os.path.exists(abslfile) and
+                    repo.dirstate.normalize(lfile) not in repo[None]):
+                    util.unlinkpath(abslfile)
+                    removed += 1
+
+        # largefile processing might be slow and be interrupted - be prepared
+        lfdirstate.write()
+
+        if lfiles:
+            if printmessage:
+                ui.status(_('getting changed largefiles\n'))
             cachelfiles(ui, repo, None, lfiles)
 
-        updated, removed = 0, 0
-        for f in lfiles:
-            i = _updatelfile(repo, lfdirstate, f)
-            if i:
-                if i > 0:
-                    updated += i
+        for lfile in lfiles:
+            update1 = 0
+
+            expecthash = update.get(lfile)
+            if expecthash:
+                if not lfutil.copyfromcache(repo, expecthash, lfile):
+                    # failed ... but already removed and set to normallookup
+                    continue
+                # Synchronize largefile dirstate to the last modified
+                # time of the file
+                lfdirstate.normal(lfile)
+                update1 = 1
+
+            # copy the state of largefile standin from the repository's
+            # dirstate to its state in the lfdirstate.
+            abslfile = repo.wjoin(lfile)
+            absstandin = repo.wjoin(lfutil.standin(lfile))
+            if os.path.exists(absstandin):
+                mode = os.stat(absstandin).st_mode
+                if mode != os.stat(abslfile).st_mode:
+                    os.chmod(abslfile, mode)
+                    update1 = 1
+
+            updated += update1
+
+            state = repo.dirstate[lfutil.standin(lfile)]
+            if state == 'n':
+                # When rebasing, we need to synchronize the standin and the
+                # largefile, because otherwise the largefile will get reverted.
+                # But for commit's sake, we have to mark the file as unclean.
+                if getattr(repo, "_isrebasing", False):
+                    lfdirstate.normallookup(lfile)
                 else:
-                    removed -= i
-            if printmessage and (removed or updated) and not printed:
-                ui.status(_('getting changed largefiles\n'))
-                printed = True
+                    lfdirstate.normal(lfile)
+            elif state == 'r':
+                lfdirstate.remove(lfile)
+            elif state == 'a':
+                lfdirstate.add(lfile)
+            elif state == '?':
+                lfdirstate.drop(lfile)
 
         lfdirstate.write()
-        if printed and printmessage:
+        if printmessage and lfiles:
             ui.status(_('%d largefiles updated, %d removed\n') % (updated,
                 removed))
     finally:
         wlock.release()
 
-def _updatelfile(repo, lfdirstate, lfile):
-    '''updates a single largefile and copies the state of its standin from
-    the repository's dirstate to its state in the lfdirstate.
-
-    returns 1 if the file was modified, -1 if the file was removed, 0 if the
-    file was unchanged, and None if the needed largefile was missing from the
-    cache.'''
-    ret = 0
-    abslfile = repo.wjoin(lfile)
-    absstandin = repo.wjoin(lfutil.standin(lfile))
-    if os.path.exists(absstandin):
-        if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
-            shutil.copyfile(abslfile, abslfile + '.orig')
-        expecthash = lfutil.readstandin(repo, lfile)
-        if (expecthash != '' and
-            (not os.path.exists(abslfile) or
-             expecthash != lfutil.hashfile(abslfile))):
-            if not lfutil.copyfromcache(repo, expecthash, lfile):
-                # use normallookup() to allocate entry in largefiles dirstate,
-                # because lack of it misleads lfilesrepo.status() into
-                # recognition that such cache missing files are REMOVED.
-                if lfile not in repo[None]: # not switched to normal file
-                    util.unlinkpath(abslfile, ignoremissing=True)
-                lfdirstate.normallookup(lfile)
-                return None # don't try to set the mode
-            else:
-                # Synchronize largefile dirstate to the last modified time of
-                # the file
-                lfdirstate.normal(lfile)
-            ret = 1
-        mode = os.stat(absstandin).st_mode
-        if mode != os.stat(abslfile).st_mode:
-            os.chmod(abslfile, mode)
-            ret = 1
-    else:
-        # Remove lfiles for which the standin is deleted, unless the
-        # lfile is added to the repository again. This happens when a
-        # largefile is converted back to a normal file: the standin
-        # disappears, but a new (normal) file appears as the lfile.
-        if (os.path.exists(abslfile) and
-            repo.dirstate.normalize(lfile) not in repo[None]):
-            util.unlinkpath(abslfile)
-            ret = -1
-    state = repo.dirstate[lfutil.standin(lfile)]
-    if state == 'n':
-        # When rebasing, we need to synchronize the standin and the largefile,
-        # because otherwise the largefile will get reverted.  But for commit's
-        # sake, we have to mark the file as unclean.
-        if getattr(repo, "_isrebasing", False):
-            lfdirstate.normallookup(lfile)
-        else:
-            lfdirstate.normal(lfile)
-    elif state == 'r':
-        lfdirstate.remove(lfile)
-    elif state == 'a':
-        lfdirstate.add(lfile)
-    elif state == '?':
-        lfdirstate.drop(lfile)
-    return ret
-
 def lfpull(ui, repo, source="default", **opts):
     """pull largefiles for the specified revisions from the specified source
 
--- a/hgext/share.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/hgext/share.py	Mon Nov 18 15:43:45 2013 -0500
@@ -59,7 +59,7 @@
         lock and lock.release()
 
     # update store, spath, sopener and sjoin of repo
-    repo.__init__(repo.baseui, repo.root)
+    repo.unfiltered().__init__(repo.baseui, repo.root)
 
 cmdtable = {
     "share":
--- a/hgext/shelve.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/hgext/shelve.py	Mon Nov 18 15:43:45 2013 -0500
@@ -610,7 +610,7 @@
         # but it doesn't update the inmemory structures, so addchangegroup
         # hooks still fire and try to operate on the missing commits.
         # Clean up manually to prevent this.
-        repo.changelog.strip(oldtiprev, tr)
+        repo.unfiltered().changelog.strip(oldtiprev, tr)
 
         unshelvecleanup(ui, repo, basename, opts)
     finally:
--- a/mercurial/cmdutil.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/mercurial/cmdutil.py	Mon Nov 18 15:43:45 2013 -0500
@@ -940,9 +940,7 @@
 
     tmpl = opts.get('template')
     style = None
-    if tmpl:
-        tmpl = templater.parsestring(tmpl, quoted=False)
-    else:
+    if not tmpl:
         style = opts.get('style')
 
     # ui settings
--- a/mercurial/obsolete.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/mercurial/obsolete.py	Mon Nov 18 15:43:45 2013 -0500
@@ -267,7 +267,8 @@
         Return the number of new marker."""
         if not _enabled:
             raise util.Abort('obsolete feature is not enabled on this repo')
-        new = [m for m in markers if m not in self._all]
+        known = set(self._all)
+        new = [m for m in markers if m not in known]
         if new:
             f = self.sopener('obsstore', 'ab')
             try:
--- a/mercurial/templater.py	Mon Nov 18 13:29:05 2013 -0200
+++ b/mercurial/templater.py	Mon Nov 18 15:43:45 2013 -0500
@@ -52,7 +52,7 @@
                     if not decode:
                         yield ('string', program[s:pos].replace('\\', r'\\'), s)
                         break
-                    yield ('string', program[s:pos].decode('string-escape'), s)
+                    yield ('string', program[s:pos], s)
                     break
                 pos += 1
             else:
@@ -80,19 +80,19 @@
     parsed = []
     pos, stop = 0, len(tmpl)
     p = parser.parser(tokenizer, elements)
-
     while pos < stop:
         n = tmpl.find('{', pos)
         if n < 0:
-            parsed.append(("string", tmpl[pos:]))
+            parsed.append(("string", tmpl[pos:].decode("string-escape")))
             break
         if n > 0 and tmpl[n - 1] == '\\':
             # escaped
-            parsed.append(("string", tmpl[pos:n - 1] + "{"))
+            parsed.append(("string",
+                           (tmpl[pos:n - 1] + "{").decode("string-escape")))
             pos = n + 1
             continue
         if n > pos:
-            parsed.append(("string", tmpl[pos:n]))
+            parsed.append(("string", tmpl[pos:n].decode("string-escape")))
 
         pd = [tmpl, n + 1, stop]
         parseres, pos = p.parse(pd)
@@ -258,6 +258,13 @@
     key = args[1][0](context, mapping, args[1][1])
     yield dictarg.get(key)
 
+def _evalifliteral(arg, context, mapping):
+    t = stringify(arg[0](context, mapping, arg[1]))
+    if arg[0] == runstring:
+        yield runtemplate(context, mapping, compiletemplate(t, context))
+    else:
+        yield t
+
 def if_(context, mapping, args):
     if not (2 <= len(args) <= 3):
         # i18n: "if" is a keyword
@@ -265,11 +272,9 @@
 
     test = stringify(args[0][0](context, mapping, args[0][1]))
     if test:
-        t = stringify(args[1][0](context, mapping, args[1][1]))
-        yield runtemplate(context, mapping, compiletemplate(t, context))
+        yield _evalifliteral(args[1], context, mapping)
     elif len(args) == 3:
-        t = stringify(args[2][0](context, mapping, args[2][1]))
-        yield runtemplate(context, mapping, compiletemplate(t, context))
+        yield _evalifliteral(args[2], context, mapping)
 
 def ifeq(context, mapping, args):
     if not (3 <= len(args) <= 4):
@@ -279,11 +284,9 @@
     test = stringify(args[0][0](context, mapping, args[0][1]))
     match = stringify(args[1][0](context, mapping, args[1][1]))
     if test == match:
-        t = stringify(args[2][0](context, mapping, args[2][1]))
-        yield runtemplate(context, mapping, compiletemplate(t, context))
+        yield _evalifliteral(args[2], context, mapping)
     elif len(args) == 4:
-        t = stringify(args[3][0](context, mapping, args[3][1]))
-        yield runtemplate(context, mapping, compiletemplate(t, context))
+        yield _evalifliteral(args[3], context, mapping)
 
 def join(context, mapping, args):
     if not (1 <= len(args) <= 2):
@@ -313,8 +316,7 @@
         raise error.ParseError(_("label expects two arguments"))
 
     # ignore args[0] (the label string) since this is supposed to be a a no-op
-    t = stringify(args[1][0](context, mapping, args[1][1]))
-    yield runtemplate(context, mapping, compiletemplate(t, context))
+    yield _evalifliteral(args[1], context, mapping)
 
 def rstdoc(context, mapping, args):
     if len(args) != 2:
--- a/mercurial/templates/paper/shortlog.tmpl	Mon Nov 18 13:29:05 2013 -0200
+++ b/mercurial/templates/paper/shortlog.tmpl	Mon Nov 18 15:43:45 2013 -0500
@@ -80,8 +80,8 @@
                 return m ? m[1] : null;
             },
             '.bigtable > tbody:nth-of-type(2)',
-            '<tr class="%class%">\
-            <td colspan="3" style="text-align: center;">%text%</td>\
+            '<tr class="%class%">\\
+            <td colspan="3" style="text-align: center;">%text%</td>\\
             </tr>'
     );
 </script>
--- a/tests/test-command-template.t	Mon Nov 18 13:29:05 2013 -0200
+++ b/tests/test-command-template.t	Mon Nov 18 15:43:45 2013 -0500
@@ -1586,3 +1586,23 @@
   h1c
   b
   a
+
+Test string escaping:
+
+  $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
+  >
+  <>\n<[>
+  <>\n<]>
+  <>\n<
+
+Test recursive evaluation:
+
+  $ hg init r
+  $ cd r
+  $ echo a > a
+  $ hg ci -Am '{rev}'
+  adding a
+  $ hg log -r 0 --template '{if(rev, desc)}\n'
+  {rev}
+  $ hg log -r 0 --template '{if(rev, "{author} {rev}")}\n'
+  test 0
--- a/tests/test-largefiles-small-disk.t	Mon Nov 18 13:29:05 2013 -0200
+++ b/tests/test-largefiles-small-disk.t	Mon Nov 18 15:43:45 2013 -0500
@@ -64,3 +64,4 @@
 The largefile is not created in .hg/largefiles:
 
   $ ls bob/.hg/largefiles
+  dirstate
--- a/tests/test-shelve.t	Mon Nov 18 13:29:05 2013 -0200
+++ b/tests/test-shelve.t	Mon Nov 18 15:43:45 2013 -0500
@@ -520,4 +520,23 @@
   $ hg status
   A d
 
+test bug 4073 we need to enable obsolete markers for it
+
+  $ cat > ../obs.py << EOF
+  > import mercurial.obsolete
+  > mercurial.obsolete._enabled = True
+  > EOF
+  $ echo '[extensions]' >> $HGRCPATH
+  $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
+  $ hg shelve
+  shelved as default
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg debugobsolete `hg --debug id -i -r 1`
+  $ hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 2 files (+1 heads)
+
   $ cd ..