--- a/hgext/mq.py Tue Dec 21 19:47:36 2010 +0900
+++ b/hgext/mq.py Wed Dec 22 13:16:00 2010 -0600
@@ -793,6 +793,19 @@
return top, patch
return None, None
+ def check_substate(self, repo):
+ '''return list of subrepos at a different revision than substate.
+ Abort if any subrepos have uncommitted changes.'''
+ inclsubs = []
+ wctx = repo[None]
+ for s in wctx.substate:
+ if wctx.sub(s).dirty(True):
+ raise util.Abort(
+ _("uncommitted changes in subrepository %s") % s)
+ elif wctx.sub(s).dirty():
+ inclsubs.append(s)
+ return inclsubs
+
def check_localchanges(self, repo, force=False, refresh=True):
m, a, r, d = repo.status()[:4]
if (m or a or r or d) and not force:
@@ -826,16 +839,23 @@
% patchfn)
else:
raise util.Abort(_('patch "%s" already exists') % patchfn)
+
+ inclsubs = self.check_substate(repo)
+ if inclsubs:
+ inclsubs.append('.hgsubstate')
if opts.get('include') or opts.get('exclude') or pats:
+ if inclsubs:
+ pats = list(pats or []) + inclsubs
match = cmdutil.match(repo, pats, opts)
# detect missing files in pats
def badfn(f, msg):
- raise util.Abort('%s: %s' % (f, msg))
+ if f != '.hgsubstate': # .hgsubstate is auto-created
+ raise util.Abort('%s: %s' % (f, msg))
match.bad = badfn
m, a, r, d = repo.status(match=match)[:4]
else:
m, a, r, d = self.check_localchanges(repo, force=True)
- match = cmdutil.matchfiles(repo, m + a + r)
+ match = cmdutil.matchfiles(repo, m + a + r + inclsubs)
if len(repo[None].parents()) > 1:
raise util.Abort(_('cannot manage merge changesets'))
commitfiles = m + a + r
@@ -1259,6 +1279,8 @@
if repo.changelog.heads(top) != [top]:
raise util.Abort(_("cannot refresh a revision with children"))
+ inclsubs = self.check_substate(repo)
+
cparents = repo.changelog.parents(top)
patchparent = self.qparents(repo, top)
ph = patchheader(self.join(patchfn), self.plainmode)
@@ -1310,18 +1332,12 @@
# local dirstate. in this case, we want them to only
# show up in the added section
for x in m:
- if x == '.hgsub' or x == '.hgsubstate':
- self.ui.warn(_('warning: not refreshing %s\n') % x)
- continue
if x not in aa:
mm.add(x)
# we might end up with files added by the local dirstate that
# were deleted by the patch. In this case, they should only
# show up in the changed section.
for x in a:
- if x == '.hgsub' or x == '.hgsubstate':
- self.ui.warn(_('warning: not adding %s\n') % x)
- continue
if x in dd:
dd.remove(x)
mm.add(x)
@@ -1331,9 +1347,6 @@
# are not in the add or change column of the patch
forget = []
for x in d + r:
- if x == '.hgsub' or x == '.hgsubstate':
- self.ui.warn(_('warning: not removing %s\n') % x)
- continue
if x in aa:
aa.remove(x)
forget.append(x)
@@ -1346,7 +1359,7 @@
r = list(dd)
a = list(aa)
c = [filter(matchfn, l) for l in (m, a, r)]
- match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2]))
+ match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2] + inclsubs))
chunks = patch.diff(repo, patchparent, match=match,
changes=c, opts=diffopts)
for chunk in chunks:
--- a/i18n/da.po Tue Dec 21 19:47:36 2010 +0900
+++ b/i18n/da.po Wed Dec 22 13:16:00 2010 -0600
@@ -17,14 +17,14 @@
msgstr ""
"Project-Id-Version: Mercurial\n"
"Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2010-11-01 11:03+0100\n"
-"PO-Revision-Date: 2010-11-01 11:11+0100\n"
+"POT-Creation-Date: 2010-12-10 12:44+0100\n"
+"PO-Revision-Date: 2010-12-10 12:46+0100\n"
"Last-Translator: <mg@lazybytes.net>\n"
"Language-Team: Danish\n"
+"Language: Danish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#, python-format
@@ -2070,6 +2070,13 @@
" antagelse af at de har miksede linieskift med vilje."
msgid ""
+"The ``win32text.forbid*`` hooks provided by the win32text extension\n"
+"have been unified into a single hook named ``eol.hook``. The hook will\n"
+"lookup the expected line endings from the ``.hgeol`` file, which means\n"
+"you must migrate to a ``.hgeol`` file first before using the hook."
+msgstr ""
+
+msgid ""
"See :hg:`help patterns` for more information about the glob patterns\n"
"used.\n"
msgstr ""
@@ -2767,8 +2774,8 @@
#, python-format
msgid "*** the current per-user limit on the number of inotify watches is %s\n"
msgstr ""
-"*** den nuværende grænse pr bruger for antallet af inotify overvågninger er %"
-"s\n"
+"*** den nuværende grænse pr bruger for antallet af inotify overvågninger er "
+"%s\n"
msgid "*** this limit is too low to watch every directory in this repository\n"
msgstr ""
@@ -2975,7 +2982,7 @@
msgid ""
"The default template mappings (view with :hg:`kwdemo -d`) can be\n"
"replaced with customized keywords and templates. Again, run\n"
-":hg:`kwdemo` to control the results of your config changes."
+":hg:`kwdemo` to control the results of your configuration changes."
msgstr ""
msgid ""
@@ -3408,7 +3415,7 @@
#, python-format
msgid "cannot write patch \"%s\": %s"
-msgstr "kan ikke skrive patch \"%s\": %s"
+msgstr "kan ikke skrive rettelse \"%s\": %s"
#, python-format
msgid "error unlinking %s\n"
@@ -3501,6 +3508,18 @@
msgid "cannot refresh a revision with children"
msgstr "kan ikke genopfriske en revision som har børn"
+#, python-format
+msgid "warning: not refreshing %s\n"
+msgstr "advarsel: genopfrisker ikke %s\n"
+
+#, python-format
+msgid "warning: not adding %s\n"
+msgstr "advarsel: tilføjer ikke %s\n"
+
+#, python-format
+msgid "warning: not removing %s\n"
+msgstr "advarsel: fjerner ikke %s\n"
+
msgid ""
"refresh interrupted while patch was popped! (revert --all, qpush to "
"recover)\n"
@@ -5362,8 +5381,8 @@
msgid "changesets"
msgstr "ændringer"
-msgid "fix unresolved conflicts with hg resolve then run hg rebase --continue"
-msgstr "ret uløste konflikter med hg resolve og kør så hg rebase --continue"
+msgid "unresolved conflicts (see hg resolve, then hg rebase --continue)"
+msgstr "uløste konflikter (se først hg resolve og dernæst hg rebase --continue)"
#, python-format
msgid "no changes, revision %d skipped\n"
@@ -5967,11 +5986,13 @@
msgid "Note that there are some limitations on using this extension:"
msgstr ""
-msgid "- You should use single encoding in one repository."
-msgstr ""
-
-msgid ""
-"\n"
+msgid ""
+"- You should use single encoding in one repository.\n"
+"- If the repository path ends with 0x5c, .hg/hgrc cannot be read.\n"
+"- win32mbcs is not compatible with fixutf8 extention."
+msgstr ""
+
+msgid ""
"By default, win32mbcs uses encoding.encoding decided by Mercurial.\n"
"You can specify the encoding by config option::"
msgstr ""
@@ -6223,8 +6244,8 @@
#, python-format
msgid "%s has not been committed yet, so no copy data will be stored for %s.\n"
msgstr ""
-"%s er endnu ikke comitted, så der vil ikke blive gemt kopieringsdata for %"
-"s.\n"
+"%s er endnu ikke comitted, så der vil ikke blive gemt kopieringsdata for "
+"%s.\n"
#, python-format
msgid "%s: not copying - file is not managed\n"
@@ -8561,7 +8582,7 @@
msgid ""
" Start a local HTTP repository browser and pull server. You can use\n"
-" this for ad-hoc sharing and browing of repositories. It is\n"
+" this for ad-hoc sharing and browsing of repositories. It is\n"
" recommended to use a real web server to serve a repository for\n"
" longer periods of time."
msgstr ""
@@ -11704,11 +11725,11 @@
msgstr ""
msgid ""
-" hg log -r \"(keyword(bug) or keyword(issue)) and not ancestors(tagged())"
-"\"\n"
-msgstr ""
-" hg log -r \"(keyword(bug) or keyword(issue)) and not ancestors(tagged())"
-"\"\n"
+" hg log -r \"(keyword(bug) or keyword(issue)) and not ancestors(tagged"
+"())\"\n"
+msgstr ""
+" hg log -r \"(keyword(bug) or keyword(issue)) and not ancestors(tagged"
+"())\"\n"
msgid ""
"Subrepositories let you nest external repositories or projects into a\n"
@@ -12167,7 +12188,7 @@
msgid ""
"Paths in the local filesystem can either point to Mercurial\n"
"repositories or to bundle files (as created by :hg:`bundle` or :hg:`\n"
-"incoming --bundle`)."
+"incoming --bundle`). See also :hg:`help paths`."
msgstr ""
msgid ""
@@ -12527,6 +12548,10 @@
msgid "working directory of %s"
msgstr "arbejdskatalog for %s"
+#, python-format
+msgid "warning: can't find ancestor for '%s' copied from '%s'!\n"
+msgstr ""
+
msgid "cannot partially commit a merge (do not specify files or patterns)"
msgstr ""
"kan ikke deponere en sammenføjning partielt (undgå at specificere filer "
@@ -13369,6 +13394,10 @@
msgstr ""
#, python-format
+msgid "warning: subrepo spec file %s not found\n"
+msgstr "advarsel: underdepot spec-fil %s blev ikke fundet\n"
+
+#, python-format
msgid "subrepo spec file %s not found"
msgstr "underdepot spec-fil %s blev ikke fundet"
@@ -13591,6 +13620,13 @@
msgid "could not symlink to %r: %s"
msgstr "kunne ikke lave et symbolsk link til %r: %s"
+msgid "check your clock"
+msgstr ""
+
+#, python-format
+msgid "negative timestamp: %d"
+msgstr ""
+
#, python-format
msgid "invalid date: %r"
msgstr "ugyldig dato: %r"
@@ -13600,6 +13636,10 @@
msgstr "dato overskrider 32 bit: %d"
#, python-format
+msgid "negative date value: %d"
+msgstr ""
+
+#, python-format
msgid "impossible time zone offset: %d"
msgstr "umuligt tidszone: %d"
--- a/i18n/de.po Tue Dec 21 19:47:36 2010 +0900
+++ b/i18n/de.po Wed Dec 22 13:16:00 2010 -0600
@@ -38,7 +38,7 @@
"Project-Id-Version: Mercurial\n"
"Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
"POT-Creation-Date: 2010-09-22 13:26+0200\n"
-"PO-Revision-Date: 2010-09-24 02:15+0200\n"
+"PO-Revision-Date: 2010-12-04 19:28+0100\n"
"Last-Translator: Martin Roppelt <m.p.roppelt@web.de>\n"
"Language-Team: German (http://transifex.net/projects/p/mercurial/team/de/) "
"<>\n"
@@ -5864,7 +5864,7 @@
msgstr "Emailadressen von CC-Empfängern"
msgid "ask for confirmation before sending"
-msgstr ""
+msgstr "Vor dem Abschicken bestätigen"
msgid "add diffstat output to messages"
msgstr "Fügt Ausgabe von diffstat hinzu"
@@ -5895,7 +5895,7 @@
msgstr "Antwortadresse (reply-to)"
msgid "flags to add in subject prefixes"
-msgstr ""
+msgstr "Diese Stichwörter zu Betreffs-Präfixen hinzufügen"
msgid "email addresses of recipients"
msgstr "Emailadressen der Empfänger"
@@ -5929,7 +5929,7 @@
msgstr "hg email [OPTION]... [ZIEL]..."
msgid "show progress bars for some actions"
-msgstr ""
+msgstr "Bei einigen Befehlen Fortschrittsbalken zeigen"
msgid ""
"This extension uses the progress information logged by hg commands\n"
@@ -5965,35 +5965,46 @@
msgstr "Löscht nicht versionierte Dateien aus dem Arbeitsverzeichnis"
msgid "removes files not tracked by Mercurial"
-msgstr ""
+msgstr "Entfernt nicht von Mercurial versionierte Dateien"
msgid ""
" Delete files not known to Mercurial. This is useful to test local\n"
" and uncommitted changes in an otherwise-clean source tree."
msgstr ""
+" Entferne Dateien, die Mercurial nicht bekannt sind. Nützlich, um\n"
+" lokale und nicht versionierte Dateien in einem ansonsten\n"
+" unveränderten Projektarchiv zu testen."
msgid " This means that purge will delete:"
-msgstr ""
+msgstr " Das heißt, purge wird das folgende löschen:"
msgid ""
" - Unknown files: files marked with \"?\" by :hg:`status`\n"
" - Empty directories: in fact Mercurial ignores directories unless\n"
" they contain files under source control management"
msgstr ""
+" - Unbekannte Dateien: Dateien, die :hg:`status` mit \"?\\\" markiert\n"
+" - Leere Verzeichnisse: Mercurial ignoriert Verzeichnisse, solange\n"
+" sie keine Dateien unter Versionsverwaltung enthalten."
msgid " But it will leave untouched:"
-msgstr ""
+msgstr " Aber das folgende unberührt lassen:"
msgid ""
" - Modified and unmodified tracked files\n"
" - Ignored files (unless --all is specified)\n"
" - New files added to the repository (with :hg:`add`)"
msgstr ""
+" - Veränderte und unveränderte Dateien unter Versionsverwaltung\n"
+" - Ignorierte Dateien (es sei denn --all wurde angegeben)\n"
+" - Neu hinzugefügte Dateien (mit :hg:`add`)"
msgid ""
" If directories are given on the command line, only files in these\n"
" directories are considered."
msgstr ""
+" Wenn auf der Befehlzeile Verzeichnisse angegeben wurden, werden\n"
+" nur Dateien in diesen Verzeichnissen einbezogen."
msgid ""
" Be careful with purge, as you could irreversibly delete some files\n"
@@ -6002,28 +6013,33 @@
" option.\n"
" "
msgstr ""
+" Seien Sie mit purge vorsichtig, da Sie Dateien unwiderbringlich\n"
+" löschen könnten, die Sie nicht zum Projektarchiv hinzugefügt\n"
+" haben. Wenn Sie nur die Liste der Dateien sehen wollen, die dieses\n"
+" Programm entfernen würde, nutzen Sie die Option --print.\n"
+" "
#, python-format
msgid "%s cannot be removed"
-msgstr ""
+msgstr "%s kann nicht entfernt werden"
#, python-format
msgid "warning: %s\n"
-msgstr ""
+msgstr "Warnung: %s\n"
#, python-format
msgid "Removing file %s\n"
-msgstr ""
+msgstr "Entferne Datei %s\n"
#, python-format
msgid "Removing directory %s\n"
-msgstr ""
+msgstr "Entferne Verzeichnis %s\n"
msgid "abort if an error occurs"
-msgstr ""
+msgstr "Bei Fehler abbrechen"
msgid "purge ignored files too"
-msgstr ""
+msgstr "Auch ignorierte Dateien entfernen"
msgid "print filenames instead of deleting them"
msgstr "Zeigt Dateinamen an, statt sie zu entfernen"
@@ -6033,7 +6049,7 @@
"Beendet Dateinamen mit NUL zur Nutzung mit xargs (implizert -p/--print)"
msgid "hg purge [OPTION]... [DIR]..."
-msgstr ""
+msgstr "hg purge [OPTION]... [DIR]..."
msgid "command to move sets of revisions to a different ancestor"
msgstr "Verknüpft Änderungssätze mit einem anderen Vorgänger"
--- a/mercurial/localrepo.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/localrepo.py Wed Dec 22 13:16:00 2010 -0600
@@ -949,7 +949,6 @@
# commit subs
if subs or removedsubs:
- pstate = subrepo.substate(self['.'])
state = wctx.substate.copy()
for s in sorted(subs):
sub = wctx.sub(s)
@@ -957,19 +956,7 @@
subrepo.subrelpath(sub))
sr = sub.commit(cctx._text, user, date)
state[s] = (state[s][0], sr)
-
- changed = False
- if len(pstate) != len(state):
- changed = True
- if not changed:
- for newstate in state:
- if state[newstate][1] != pstate[newstate]:
- changed = True
- if changed:
- subrepo.writestate(self, state)
- elif (changes[0] == ['.hgsubstate'] and changes[1] == [] and
- changes[2] == []):
- return None
+ subrepo.writestate(self, state)
# Save commit message in case this transaction gets rolled back
# (e.g. by a pretxncommit hook). Leave the content alone on
--- a/mercurial/parser.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/parser.py Wed Dec 22 13:16:00 2010 -0600
@@ -22,6 +22,7 @@
self._tokenizer = tokenizer
self._elements = elements
self._methods = methods
+ self.current = None
def _advance(self):
'advance the tokenizer'
t = self.current
@@ -76,7 +77,7 @@
def parse(self, message):
'generate a parse tree from a message'
self._iter = self._tokenizer(message)
- self.current = self._iter.next()
+ self._advance()
return self._parse()
def eval(self, tree):
'recursively evaluate a parse tree using node methods'
--- a/mercurial/store.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/store.py Wed Dec 22 13:16:00 2010 -0600
@@ -323,7 +323,8 @@
self.fncache.rewrite(existing)
def copylist(self):
- d = _data + ' dh fncache'
+ d = ('data dh fncache'
+ ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i')
return (['requires', '00changelog.i'] +
[self.pathjoiner('store', f) for f in d.split()])
--- a/mercurial/subrepo.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/subrepo.py Wed Dec 22 13:16:00 2010 -0600
@@ -13,19 +13,6 @@
nullstate = ('', '', 'empty')
-
-def substate(ctx):
- rev = {}
- if '.hgsubstate' in ctx:
- try:
- for l in ctx['.hgsubstate'].data().splitlines():
- revision, path = l.split(" ", 1)
- rev[path] = revision
- except IOError, err:
- if err.errno != errno.ENOENT:
- raise
- return rev
-
def state(ctx, ui):
"""return a state dict, mapping subrepo paths configured in .hgsub
to tuple: (source from .hgsub, revision from .hgsubstate, kind
@@ -52,7 +39,15 @@
for path, src in ui.configitems('subpaths'):
p.set('subpaths', path, src, ui.configsource('subpaths', path))
- rev = substate(ctx)
+ rev = {}
+ if '.hgsubstate' in ctx:
+ try:
+ for l in ctx['.hgsubstate'].data().splitlines():
+ revision, path = l.split(" ", 1)
+ rev[path] = revision
+ except IOError, err:
+ if err.errno != errno.ENOENT:
+ raise
state = {}
for path, src in p[''].items():
@@ -177,6 +172,8 @@
def subrelpath(sub):
"""return path to this subrepo as seen from outermost repo"""
+ if hasattr(sub, '_relpath'):
+ return sub._relpath
if not hasattr(sub, '_repo'):
return sub._path
return reporelpath(sub._repo)
@@ -241,9 +238,10 @@
class abstractsubrepo(object):
- def dirty(self):
- """returns true if the dirstate of the subrepo does not match
- current stored state
+ def dirty(self, ignoreupdate=False):
+ """returns true if the dirstate of the subrepo is dirty or does not
+ match current stored state. If ignoreupdate is true, only check
+ whether the subrepo has uncommitted changes in its dirstate.
"""
raise NotImplementedError
@@ -395,12 +393,13 @@
s = subrepo(ctx, subpath)
s.archive(ui, archiver, os.path.join(prefix, self._path))
- def dirty(self):
+ def dirty(self, ignoreupdate=False):
r = self._state[1]
- if r == '':
+ if r == '' and not ignoreupdate: # no state recorded
return True
w = self._repo[None]
- if w.p1() != self._repo[r]: # version checked out change
+ # version checked out changed?
+ if w.p1() != self._repo[r] and not ignoreupdate:
return True
return w.dirty() # working directory changed
@@ -543,9 +542,10 @@
return True, True
return bool(changes), False
- def dirty(self):
- if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
- return False
+ def dirty(self, ignoreupdate=False):
+ if not self._wcchanged()[0]:
+ if self._wcrev() == self._state[1] and not ignoreupdate:
+ return False
return True
def commit(self, text, user, date):
@@ -619,15 +619,17 @@
# TODO add git version check.
self._state = state
self._ctx = ctx
- self._relpath = path
- self._path = ctx._repo.wjoin(path)
+ self._path = path
+ self._relpath = os.path.join(reporelpath(ctx._repo), path)
+ self._abspath = ctx._repo.wjoin(path)
self._ui = ctx._repo.ui
def _gitcommand(self, commands, env=None, stream=False):
return self._gitdir(commands, env=env, stream=stream)[0]
def _gitdir(self, commands, env=None, stream=False):
- return self._gitnodir(commands, env=env, stream=stream, cwd=self._path)
+ return self._gitnodir(commands, env=env, stream=stream,
+ cwd=self._abspath)
def _gitnodir(self, commands, env=None, stream=False, cwd=None):
"""Calls the git command
@@ -680,32 +682,42 @@
return base == r1
def _gitbranchmap(self):
- '''returns 3 things:
+ '''returns 2 things:
a map from git branch to revision
- a map from revision to branches
- a map from remote branch to local tracking branch'''
+ a map from revision to branches'''
branch2rev = {}
rev2branch = {}
- tracking = {}
+
out = self._gitcommand(['for-each-ref', '--format',
- '%(objectname) %(refname) %(upstream) end'])
+ '%(objectname) %(refname)'])
for line in out.split('\n'):
- revision, ref, upstream = line.split(' ')[:3]
+ revision, ref = line.split(' ')
if ref.startswith('refs/tags/'):
continue
if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
continue # ignore remote/HEAD redirects
branch2rev[ref] = revision
rev2branch.setdefault(revision, []).append(ref)
- if upstream:
- # assumes no more than one local tracking branch for a remote
- tracking[upstream] = ref
- return branch2rev, rev2branch, tracking
+ return branch2rev, rev2branch
+
+ def _gittracking(self, branches):
+ 'return map of remote branch to local tracking branch'
+ # assumes no more than one local tracking branch for each remote
+ tracking = {}
+ for b in branches:
+ if b.startswith('refs/remotes/'):
+ continue
+ remote = self._gitcommand(['config', 'branch.%s.remote' % b])
+ if remote:
+ ref = self._gitcommand(['config', 'branch.%s.merge' % b])
+ tracking['refs/remotes/%s/%s' %
+ (remote, ref.split('/', 2)[2])] = b
+ return tracking
def _fetch(self, source, revision):
- if not os.path.exists('%s/.git' % self._path):
+ if not os.path.exists(os.path.join(self._abspath, '.git')):
self._ui.status(_('cloning subrepo %s\n') % self._relpath)
- self._gitnodir(['clone', source, self._path])
+ self._gitnodir(['clone', source, self._abspath])
if self._githavelocally(revision):
return
self._ui.status(_('pulling subrepo %s\n') % self._relpath)
@@ -717,10 +729,11 @@
self._gitcommand(['fetch', source])
if not self._githavelocally(revision):
raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
- (revision, self._path))
+ (revision, self._relpath))
- def dirty(self):
- if self._state[1] != self._gitstate(): # version checked out changed?
+ def dirty(self, ignoreupdate=False):
+ # version checked out changed?
+ if not ignoreupdate and self._state[1] != self._gitstate():
return True
# check for staged changes or modified files; ignore untracked files
out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
@@ -737,7 +750,7 @@
return
elif self._gitstate() == revision:
return
- branch2rev, rev2branch, tracking = self._gitbranchmap()
+ branch2rev, rev2branch = self._gitbranchmap()
def rawcheckout():
# no branch to checkout, check it out with no branch
@@ -763,6 +776,7 @@
self._gitcommand(['checkout', firstlocalbranch])
return
+ tracking = self._gittracking(branch2rev.keys())
# choose a remote branch already tracked if possible
remote = branches[0]
if remote not in tracking:
@@ -815,7 +829,7 @@
def push(self, force):
# if a branch in origin contains the revision, nothing to do
- branch2rev, rev2branch, tracking = self._gitbranchmap()
+ branch2rev, rev2branch = self._gitbranchmap()
if self._state[1] in rev2branch:
for b in rev2branch[self._state[1]]:
if b.startswith('refs/remotes/origin/'):
@@ -849,16 +863,16 @@
def remove(self):
if self.dirty():
self._ui.warn(_('not removing repo %s because '
- 'it has changes.\n') % self._path)
+ 'it has changes.\n') % self._relpath)
return
# we can't fully delete the repository as it may contain
# local-only history
- self._ui.note(_('removing subrepo %s\n') % self._path)
+ self._ui.note(_('removing subrepo %s\n') % self._relpath)
self._gitcommand(['config', 'core.bare', 'true'])
- for f in os.listdir(self._path):
+ for f in os.listdir(self._abspath):
if f == '.git':
continue
- path = os.path.join(self._path, f)
+ path = os.path.join(self._abspath, f)
if os.path.isdir(path) and not os.path.islink(path):
shutil.rmtree(path)
else:
@@ -876,14 +890,42 @@
relpath = subrelpath(self)
ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
for i, info in enumerate(tar):
- archiver.addfile(os.path.join(prefix, self._relpath, info.name),
- info.mode, info.issym(),
- tar.extractfile(info).read())
+ if info.isdir():
+ continue
+ if info.issym():
+ data = info.linkname
+ else:
+ data = tar.extractfile(info).read()
+ archiver.addfile(os.path.join(prefix, self._path, info.name),
+ info.mode, info.issym(), data)
ui.progress(_('archiving (%s)') % relpath, i + 1,
unit=_('files'))
ui.progress(_('archiving (%s)') % relpath, None)
+ def status(self, rev2, **opts):
+ rev1 = self._state[1]
+ modified, added, removed = [], [], []
+ if rev2:
+ command = ['diff-tree', rev1, rev2]
+ else:
+ command = ['diff-index', rev1]
+ out = self._gitcommand(command)
+ for line in out.split('\n'):
+ tab = line.find('\t')
+ if tab == -1:
+ continue
+ status, f = line[tab - 1], line[tab + 1:]
+ if status == 'M':
+ modified.append(f)
+ elif status == 'A':
+ added.append(f)
+ elif status == 'D':
+ removed.append(f)
+
+ deleted = unknown = ignored = clean = []
+ return modified, added, removed, deleted, unknown, ignored, clean
+
types = {
'hg': hgsubrepo,
'svn': svnsubrepo,
--- a/mercurial/templater.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/templater.py Wed Dec 22 13:16:00 2010 -0600
@@ -7,7 +7,192 @@
from i18n import _
import sys, os
-import util, config, templatefilters
+import util, config, templatefilters, parser, error
+
+# template parsing
+
+elements = {
+ "(": (20, ("group", 1, ")"), ("func", 1, ")")),
+ ",": (2, None, ("list", 2)),
+ "|": (5, None, ("|", 5)),
+ "%": (6, None, ("%", 6)),
+ ")": (0, None, None),
+ "symbol": (0, ("symbol",), None),
+ "string": (0, ("string",), None),
+ "end": (0, None, None),
+}
+
+def tokenizer(data):
+ program, start, end = data
+ pos = start
+ while pos < end:
+ c = program[pos]
+ if c.isspace(): # skip inter-token whitespace
+ pass
+ elif c in "(,)%|": # handle simple operators
+ yield (c, None, pos)
+ elif (c in '"\'' or c == 'r' and
+ program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
+ if c == 'r':
+ pos += 1
+ c = program[pos]
+ decode = lambda x: x
+ else:
+ decode = lambda x: x.decode('string-escape')
+ pos += 1
+ s = pos
+ while pos < end: # find closing quote
+ d = program[pos]
+ if d == '\\': # skip over escaped characters
+ pos += 2
+ continue
+ if d == c:
+ yield ('string', decode(program[s:pos]), s)
+ break
+ pos += 1
+ else:
+ raise error.ParseError(_("unterminated string"), s)
+ elif c.isalnum() or c in '_':
+ s = pos
+ pos += 1
+ while pos < end: # find end of symbol
+ d = program[pos]
+ if not (d.isalnum() or d == "_"):
+ break
+ pos += 1
+ sym = program[s:pos]
+ yield ('symbol', sym, s)
+ pos -= 1
+ elif c == '}':
+ pos += 1
+ break
+ else:
+ raise error.ParseError(_("syntax error"), pos)
+ pos += 1
+ data[2] = pos
+ yield ('end', None, pos)
+
+def compiletemplate(tmpl, context):
+ 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:]))
+ break
+ if n > 0 and tmpl[n - 1] == '\\':
+ # escaped
+ parsed.append(("string", tmpl[pos:n - 1] + "{"))
+ pos = n + 1
+ continue
+ if n > pos:
+ parsed.append(("string", tmpl[pos:n]))
+
+ pd = [tmpl, n + 1, stop]
+ parsed.append(p.parse(pd))
+ pos = pd[2]
+
+ return [compileexp(e, context) for e in parsed]
+
+def compileexp(exp, context):
+ t = exp[0]
+ if t in methods:
+ return methods[t](exp, context)
+ raise error.ParseError(_("unknown method '%s'") % t)
+
+# template evaluation
+
+def getsymbol(exp):
+ if exp[0] == 'symbol':
+ return exp[1]
+ raise error.ParseError(_("expected a symbol"))
+
+def getlist(x):
+ if not x:
+ return []
+ if x[0] == 'list':
+ return getlist(x[1]) + [x[2]]
+ return [x]
+
+def getfilter(exp, context):
+ f = getsymbol(exp)
+ if f not in context._filters:
+ raise error.ParseError(_("unknown function '%s'") % f)
+ return context._filters[f]
+
+def gettemplate(exp, context):
+ if exp[0] == 'string':
+ return compiletemplate(exp[1], context)
+ if exp[0] == 'symbol':
+ return context._load(exp[1])
+ raise error.ParseError(_("expected template specifier"))
+
+def runstring(context, mapping, data):
+ return data
+
+def runsymbol(context, mapping, key):
+ v = mapping.get(key)
+ if v is None:
+ v = context._defaults.get(key, '')
+ if hasattr(v, '__call__'):
+ return v(**mapping)
+ return v
+
+def buildfilter(exp, context):
+ func, data = compileexp(exp[1], context)
+ filt = getfilter(exp[2], context)
+ return (runfilter, (func, data, filt))
+
+def runfilter(context, mapping, data):
+ func, data, filt = data
+ return filt(func(context, mapping, data))
+
+def buildmap(exp, context):
+ func, data = compileexp(exp[1], context)
+ ctmpl = gettemplate(exp[2], context)
+ return (runmap, (func, data, ctmpl))
+
+def runmap(context, mapping, data):
+ func, data, ctmpl = data
+ d = func(context, mapping, data)
+ lm = mapping.copy()
+
+ for i in d:
+ if isinstance(i, dict):
+ lm.update(i)
+ for f, d in ctmpl:
+ yield f(context, lm, d)
+ else:
+ # v is not an iterable of dicts, this happen when 'key'
+ # has been fully expanded already and format is useless.
+ # If so, return the expanded value.
+ yield i
+
+def buildfunc(exp, context):
+ n = getsymbol(exp[1])
+ args = [compileexp(x, context) for x in getlist(exp[2])]
+ if n in context._filters:
+ if len(args) != 1:
+ raise error.ParseError(_("filter %s expects one argument") % n)
+ f = context._filters[n]
+ return (runfilter, (args[0][0], args[0][1], f))
+ elif n in context._funcs:
+ f = context._funcs[n]
+ return (f, args)
+
+methods = {
+ "string": lambda e, c: (runstring, e[1]),
+ "symbol": lambda e, c: (runsymbol, e[1]),
+ "group": lambda e, c: compileexp(e[1], c),
+# ".": buildmember,
+ "|": buildfilter,
+ "%": buildmap,
+ "func": buildfunc,
+ }
+
+# template engine
path = ['templates', '../templates']
stringify = templatefilters.stringify
@@ -66,104 +251,18 @@
self._defaults = defaults
self._cache = {}
+ def _load(self, t):
+ '''load, parse, and cache a template'''
+ if t not in self._cache:
+ self._cache[t] = compiletemplate(self._loader(t), self)
+ return self._cache[t]
+
def process(self, t, mapping):
'''Perform expansion. t is name of map element to expand.
mapping contains added elements for use during expansion. Is a
generator.'''
- return _flatten(self._process(self._load(t), mapping))
-
- def _load(self, t):
- '''load, parse, and cache a template'''
- if t not in self._cache:
- self._cache[t] = self._parse(self._loader(t))
- return self._cache[t]
-
- def _get(self, mapping, key):
- v = mapping.get(key)
- if v is None:
- v = self._defaults.get(key, '')
- if hasattr(v, '__call__'):
- v = v(**mapping)
- return v
-
- def _filter(self, mapping, parts):
- filters, val = parts
- x = self._get(mapping, val)
- for f in filters:
- x = f(x)
- return x
-
- def _format(self, mapping, args):
- key, parsed = args
- v = self._get(mapping, key)
- if not hasattr(v, '__iter__'):
- raise SyntaxError(_("error expanding '%s%%%s'")
- % (key, parsed))
- lm = mapping.copy()
- for i in v:
- if isinstance(i, dict):
- lm.update(i)
- yield self._process(parsed, lm)
- else:
- # v is not an iterable of dicts, this happen when 'key'
- # has been fully expanded already and format is useless.
- # If so, return the expanded value.
- yield i
-
- def _parse(self, tmpl):
- '''preparse a template'''
- parsed = []
- pos, stop = 0, len(tmpl)
- while pos < stop:
- n = tmpl.find('{', pos)
- if n < 0:
- parsed.append((None, tmpl[pos:stop]))
- break
- if n > 0 and tmpl[n - 1] == '\\':
- # escaped
- parsed.append((None, tmpl[pos:n - 1] + "{"))
- pos = n + 1
- continue
- if n > pos:
- parsed.append((None, tmpl[pos:n]))
-
- pos = n
- n = tmpl.find('}', pos)
- if n < 0:
- # no closing
- parsed.append((None, tmpl[pos:stop]))
- break
-
- expr = tmpl[pos + 1:n]
- pos = n + 1
-
- if '%' in expr:
- # the keyword should be formatted with a template
- key, t = expr.split('%')
- parsed.append((self._format, (key.strip(),
- self._load(t.strip()))))
- elif '|' in expr:
- # process the keyword value with one or more filters
- parts = expr.split('|')
- val = parts[0].strip()
- try:
- filters = [self._filters[f.strip()] for f in parts[1:]]
- except KeyError, i:
- raise SyntaxError(_("unknown filter '%s'") % i[0])
- parsed.append((self._filter, (filters, val)))
- else:
- # just get the keyword
- parsed.append((self._get, expr.strip()))
-
- return parsed
-
- def _process(self, parsed, mapping):
- '''Render a template. Returns a generator.'''
- for f, e in parsed:
- if f:
- yield f(mapping, e)
- else:
- yield e
+ return _flatten(func(self, mapping, data) for func, data in
+ self._load(t))
engines = {'default': engine}
@@ -214,6 +313,8 @@
if not t in self.cache:
try:
self.cache[t] = open(self.map[t][1]).read()
+ except KeyError, inst:
+ raise util.Abort(_('"%s" not in template map') % inst.args[0])
except IOError, inst:
raise IOError(inst.args[0], _('template file %s: %s') %
(self.map[t][1], inst.args[1]))
--- a/mercurial/templates/paper/branches.tmpl Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/templates/paper/branches.tmpl Wed Dec 22 13:16:00 2010 -0600
@@ -40,7 +40,18 @@
<th>branch</th>
<th>node</th>
</tr>
-{entries%branchentry}
+{entries %
+' <tr class="tagEntry parity{parity}">
+ <td>
+ <a href="{url}shortlog/{node|short}{sessionvars%urlparameter}" class="{status}">
+ {branch|escape}
+ </a>
+ </td>
+ <td class="node">
+ {node|short}
+ </td>
+ </tr>'
+}
</table>
</div>
</div>
--- a/mercurial/templates/paper/shortlogentry.tmpl Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/templates/paper/shortlogentry.tmpl Wed Dec 22 13:16:00 2010 -0600
@@ -1,5 +1,5 @@
<tr class="parity{parity}">
- <td class="age">{date|age}</td>
+ <td class="age">{age(date)}</td>
<td class="author">{author|person}</td>
- <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}</td>
+ <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}</td>
</tr>
--- a/mercurial/url.py Tue Dec 21 19:47:36 2010 +0900
+++ b/mercurial/url.py Wed Dec 22 13:16:00 2010 -0600
@@ -546,7 +546,7 @@
self.host)
else:
self.ui.warn(_("warning: %s certificate not verified "
- "(check web.cacerts config setting)\n") %
+ "(check web.cacerts config setting)\n") %
self.host)
httplib.HTTPSConnection.connect(self)
--- a/tests/test-command-template.t Tue Dec 21 19:47:36 2010 +0900
+++ b/tests/test-command-template.t Wed Dec 22 13:16:00 2010 -0600
@@ -449,7 +449,7 @@
$ echo 'q = q' > t
$ hg log --style ./t
- abort: ./t: no key named 'changeset'
+ abort: "changeset" not in template map
[255]
Error if include fails:
--- a/tests/test-mq-qrefresh.t Tue Dec 21 19:47:36 2010 +0900
+++ b/tests/test-mq-qrefresh.t Wed Dec 22 13:16:00 2010 -0600
@@ -487,74 +487,3 @@
$ cd ..
-
-Issue2499: refuse to add .hgsub{,state} to a patch
-
- $ hg init repo-2499
- $ cd repo-2499
- $ hg qinit
- $ hg qnew -m 0 0.diff
- $ echo a > a
- $ hg init sub
- $ cd sub
- $ echo b > b
- $ hg ci -Am 0sub
- adding b
- $ cd ..
-
-test when adding
- $ echo sub = sub > .hgsub
- $ echo `hg id -i --debug sub` sub > .hgsubstate
- $ hg add
- adding .hgsub
- adding .hgsubstate
- adding a
- $ hg qrefresh
- warning: not adding .hgsub
- warning: not adding .hgsubstate
- $ hg qfinish -a
- $ hg status
- A .hgsub
- A .hgsubstate
- $ hg forget .hgsubstate
- $ rm .hgsubstate
-
-add subrepo with a real commit
- $ hg ci -m 1
- committing subrepository sub
- $ hg qnew -m 2 2.diff
-
-test when modifying
- $ echo sub2 = sub2 >> .hgsub
- $ hg qrefresh
- warning: not refreshing .hgsub
- $ echo 0000000000000000000000000000000000000000 sub2 >> .hgsubstate
- $ hg qrefresh
- warning: not refreshing .hgsub
- warning: not refreshing .hgsubstate
- $ hg revert --no-backup .hgsub .hgsubstate
-
-test when removing
- $ hg rm .hgsub
- $ hg rm .hgsubstate
- $ hg qrefresh
- warning: not removing .hgsub
- warning: not removing .hgsubstate
- $ hg status
- R .hgsub
- R .hgsubstate
- $ hg revert --no-backup .hgsub .hgsubstate
-
-test when deleting
- $ rm .hgsub .hgsubstate
- $ hg qrefresh
- warning: not removing .hgsub
- warning: not removing .hgsubstate
- warning: subrepo spec file .hgsub not found
- $ hg status
- ! .hgsub
- ! .hgsubstate
- $ hg cat -r1 .hgsub > .hgsub
- $ hg revert --no-backup .hgsubstate
-
- $ cd ..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mq-subrepo.t Wed Dec 22 13:16:00 2010 -0600
@@ -0,0 +1,342 @@
+ $ echo "[extensions]" >> $HGRCPATH
+ $ echo "mq=" >> $HGRCPATH
+ $ echo "record=" >> $HGRCPATH
+ $ echo "[diff]" >> $HGRCPATH
+ $ echo "nodates=1" >> $HGRCPATH
+
+fn to create new repository w/dirty subrepo, and cd into it
+ $ mkrepo() {
+ > hg init $1
+ > cd $1
+ > hg qinit
+ > }
+
+fn to create dirty subrepo
+ $ mksubrepo() {
+ > hg init $1
+ > cd $1
+ > echo a > a
+ > hg add
+ > cd ..
+ > }
+
+ $ testadd() {
+ > local stdin=`cat`
+ > mksubrepo sub
+ > echo sub = sub >> .hgsub
+ > hg add .hgsub
+ > echo % abort when adding .hgsub w/dirty subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > echo [$?]
+ > hg -R sub ci -m0sub
+ > echo % update substate when adding .hgsub w/clean updated subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > hg debugsub
+ > }
+
+ $ testmod() {
+ > local stdin=`cat`
+ > mksubrepo sub2
+ > echo sub2 = sub2 >> .hgsub
+ > echo % abort when modifying .hgsub w/dirty subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > echo [$?]
+ > hg -R sub2 ci -m0sub2
+ > echo % update substate when modifying .hgsub w/clean updated subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > hg debugsub
+ > }
+
+ $ testrm1() {
+ > mksubrepo sub3
+ > echo sub3 = sub3 >> .hgsub
+ > hg ci -Aqmsub3
+ > $EXTRA
+ > echo b >> sub3/a
+ > hg rm .hgsub
+ > echo % update substate when removing .hgsub w/dirty subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > echo % debugsub should be empty
+ > hg debugsub
+ > }
+ $ testrm2() {
+ > mksubrepo sub4
+ > echo sub4 = sub4 >> .hgsub
+ > hg ci -Aqmsub4
+ > $EXTRA
+ > hg rm .hgsub
+ > echo % update substate when removing .hgsub w/clean updated subrepo
+ > hg status -S
+ > echo '%' $*
+ > echo "$stdin" | hg $*
+ > echo % debugsub should be empty
+ > hg debugsub
+ > }
+
+
+handle subrepos safely on qnew
+
+ $ mkrepo repo-2499-qnew
+ $ testadd qnew -m0 0.diff
+ adding a
+ % abort when adding .hgsub w/dirty subrepo
+ A .hgsub
+ A sub/a
+ % qnew -m0 0.diff
+ abort: uncommitted changes in subrepository sub
+ [255]
+ % update substate when adding .hgsub w/clean updated subrepo
+ A .hgsub
+ % qnew -m0 0.diff
+ committing subrepository sub
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+
+ $ testmod qnew -m1 1.diff
+ adding a
+ % abort when modifying .hgsub w/dirty subrepo
+ M .hgsub
+ A sub2/a
+ % qnew -m1 1.diff
+ abort: uncommitted changes in subrepository sub2
+ [255]
+ % update substate when modifying .hgsub w/clean updated subrepo
+ M .hgsub
+ % qnew -m1 1.diff
+ committing subrepository sub2
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+ path sub2
+ source sub2
+ revision 1f94c7611cc6b74f5a17b16121a1170d44776845
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ testrm1 qnew -m2 2.diff
+ adding a
+ % update substate when removing .hgsub w/dirty subrepo
+ M sub3/a
+ R .hgsub
+ % qnew -m2 2.diff
+ % debugsub should be empty
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ testrm2 qnew -m3 3.diff
+ adding a
+ % update substate when removing .hgsub w/clean updated subrepo
+ R .hgsub
+ % qnew -m3 3.diff
+ % debugsub should be empty
+
+ $ cd ..
+
+
+handle subrepos safely on qrefresh
+
+ $ mkrepo repo-2499-qrefresh
+ $ hg qnew -m0 0.diff
+ $ testadd qrefresh
+ adding a
+ % abort when adding .hgsub w/dirty subrepo
+ A .hgsub
+ A sub/a
+ % qrefresh
+ abort: uncommitted changes in subrepository sub
+ [255]
+ % update substate when adding .hgsub w/clean updated subrepo
+ A .hgsub
+ % qrefresh
+ committing subrepository sub
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+
+ $ hg qnew -m1 1.diff
+ $ testmod qrefresh
+ adding a
+ % abort when modifying .hgsub w/dirty subrepo
+ M .hgsub
+ A sub2/a
+ % qrefresh
+ abort: uncommitted changes in subrepository sub2
+ [255]
+ % update substate when modifying .hgsub w/clean updated subrepo
+ M .hgsub
+ % qrefresh
+ committing subrepository sub2
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+ path sub2
+ source sub2
+ revision 1f94c7611cc6b74f5a17b16121a1170d44776845
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ EXTRA='hg qnew -m2 2.diff' testrm1 qrefresh
+ adding a
+ % update substate when removing .hgsub w/dirty subrepo
+ M sub3/a
+ R .hgsub
+ % qrefresh
+ % debugsub should be empty
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ EXTRA='hg qnew -m3 3.diff' testrm2 qrefresh
+ adding a
+ % update substate when removing .hgsub w/clean updated subrepo
+ R .hgsub
+ % qrefresh
+ % debugsub should be empty
+
+ $ cd ..
+
+
+handle subrepos safely on qpush/qpop
+
+ $ mkrepo repo-2499-qpush
+ $ mksubrepo sub
+ adding a
+ $ hg -R sub ci -m0sub
+ $ echo sub = sub > .hgsub
+ $ hg add .hgsub
+ $ hg qnew -m0 0.diff
+ committing subrepository sub
+ $ hg debugsub
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+
+qpop
+ $ hg qpop
+ popping 0.diff
+ patch queue now empty
+ $ hg status -AS
+ $ hg debugsub
+
+qpush
+ $ hg qpush
+ applying 0.diff
+ now at: 0.diff
+ $ hg status -AS
+ C .hgsub
+ C .hgsubstate
+ C sub/a
+ $ hg debugsub
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+
+ $ cd ..
+
+
+handle subrepos safely on qrecord
+
+ $ mkrepo repo-2499-qrecord
+ $ testadd qrecord --config ui.interactive=1 -m0 0.diff <<EOF
+ > y
+ > y
+ > EOF
+ adding a
+ % abort when adding .hgsub w/dirty subrepo
+ A .hgsub
+ A sub/a
+ % qrecord --config ui.interactive=1 -m0 0.diff
+ diff --git a/.hgsub b/.hgsub
+ new file mode 100644
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ abort: uncommitted changes in subrepository sub
+ [255]
+ % update substate when adding .hgsub w/clean updated subrepo
+ A .hgsub
+ % qrecord --config ui.interactive=1 -m0 0.diff
+ diff --git a/.hgsub b/.hgsub
+ new file mode 100644
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ committing subrepository sub
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+
+ $ testmod qrecord --config ui.interactive=1 -m1 1.diff <<EOF
+ > y
+ > y
+ > EOF
+ adding a
+ % abort when modifying .hgsub w/dirty subrepo
+ M .hgsub
+ A sub2/a
+ % qrecord --config ui.interactive=1 -m1 1.diff
+ diff --git a/.hgsub b/.hgsub
+ 1 hunks, 1 lines changed
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ @@ -1,1 +1,2 @@
+ sub = sub
+ +sub2 = sub2
+ record this change to '.hgsub'? [Ynsfdaq?]
+ abort: uncommitted changes in subrepository sub2
+ [255]
+ % update substate when modifying .hgsub w/clean updated subrepo
+ M .hgsub
+ % qrecord --config ui.interactive=1 -m1 1.diff
+ diff --git a/.hgsub b/.hgsub
+ 1 hunks, 1 lines changed
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ @@ -1,1 +1,2 @@
+ sub = sub
+ +sub2 = sub2
+ record this change to '.hgsub'? [Ynsfdaq?]
+ committing subrepository sub2
+ path sub
+ source sub
+ revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+ path sub2
+ source sub2
+ revision 1f94c7611cc6b74f5a17b16121a1170d44776845
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ EXTRA= testrm1 qrecord --config ui.interactive=1 -m2 2.diff <<EOF
+ > y
+ > y
+ > EOF
+ adding a
+ % update substate when removing .hgsub w/dirty subrepo
+ M sub3/a
+ R .hgsub
+ % qrecord --config ui.interactive=1 -m2 2.diff
+ diff --git a/.hgsub b/.hgsub
+ deleted file mode 100644
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ % debugsub should be empty
+
+ $ hg qpop -qa
+ patch queue now empty
+ $ EXTRA= testrm2 qrecord --config ui.interactive=1 -m3 3.diff <<EOF
+ > y
+ > y
+ > EOF
+ adding a
+ % update substate when removing .hgsub w/clean updated subrepo
+ R .hgsub
+ % qrecord --config ui.interactive=1 -m3 3.diff
+ diff --git a/.hgsub b/.hgsub
+ deleted file mode 100644
+ examine changes to '.hgsub'? [Ynsfdaq?]
+ % debugsub should be empty
+
+ $ cd ..
--- a/tests/test-subrepo-empty-commit.t Tue Dec 21 19:47:36 2010 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
- $ hg init
- $ hg init sub
- $ echo 'sub = sub' > .hgsub
- $ hg add .hgsub
- $ echo c1 > f1
- $ echo c2 > sub/f2
- $ hg add -S
- adding f1
- adding sub/f2
- $ hg commit -m0
- committing subrepository sub
-
-Make .hgsubstate dirty:
-
- $ echo '0000000000000000000000000000000000000000 sub' > .hgsubstate
- $ hg diff --nodates
- diff -r 853ea21970bb .hgsubstate
- --- a/.hgsubstate
- +++ b/.hgsubstate
- @@ -1,1 +1,1 @@
- -5bbc614a5b06ad7f3bf7c2463d74b005324f34c1 sub
- +0000000000000000000000000000000000000000 sub
-
-trying to do an empty commit:
-
- $ hg commit -m1
- committing subrepository sub
- nothing changed
- [1]
-
-an okay update of .hgsubstate
- $ cd sub
- $ echo c3 > f2
- $ hg commit -m "Sub commit"
- $ cd ..
- $ hg commit -m "Updated sub"
- committing subrepository sub
-
-deleting again:
- $ echo '' > .hgsub
- $ hg commit -m2
- $ cat .hgsub
-
- $ cat .hgsubstate
-
-an okay commit, but with a dirty .hgsubstate
- $ echo 'sub = sub' > .hgsub
- $ hg commit -m3
- committing subrepository sub
- $ echo '0000000000000000000000000000000000000000 sub' > .hgsubstate
- $ hg diff --nodates
- diff -r 41e1dee3d5d9 .hgsubstate
- --- a/.hgsubstate
- +++ b/.hgsubstate
- @@ -1,1 +1,1 @@
- -fe0229ee9a0a38b43163c756bb51b94228b118e7 sub
- +0000000000000000000000000000000000000000 sub
- $ echo c4 > f3
- $ hg add f3
- $ hg status
- M .hgsubstate
- A f3
- $ hg commit -m4
- committing subrepository sub
--- a/tests/test-subrepo-git.t Tue Dec 21 19:47:36 2010 +0900
+++ b/tests/test-subrepo-git.t Wed Dec 22 13:16:00 2010 -0600
@@ -34,7 +34,7 @@
$ git clone -q ../gitroot s
$ hg add .hgsub
$ hg commit -m 'new git subrepo'
- committing subrepository $TESTTMP/t/s
+ committing subrepository s
$ hg debugsub
path s
source ../gitroot
@@ -52,8 +52,10 @@
$ git checkout -q -b testing origin/testing >/dev/null
$ cd ..
+ $ hg status --subrepos
+ M s/g
$ hg commit -m 'update git subrepo'
- committing subrepository $TESTTMP/t/s
+ committing subrepository s
$ hg debugsub
path s
source ../gitroot
@@ -99,8 +101,10 @@
$ cd ../ta
$ echo ggg >> s/g
+ $ hg status --subrepos
+ M s/g
$ hg commit -m ggg
- committing subrepository $TESTTMP/ta/s
+ committing subrepository s
$ hg debugsub
path s
source ../gitroot
@@ -119,8 +123,10 @@
$ git add f
$ cd ..
+ $ hg status --subrepos
+ A s/f
$ hg commit -m f
- committing subrepository $TESTTMP/tb/s
+ committing subrepository s
$ hg debugsub
path s
source ../gitroot
@@ -159,7 +165,11 @@
gg
ggg
$ hg commit -m 'merge'
- committing subrepository $TESTTMP/ta/s
+ committing subrepository s
+ $ hg status --subrepos --rev 1:5
+ M .hgsubstate
+ M s/g
+ A s/f
$ hg debugsub
path s
source ../gitroot
@@ -212,7 +222,7 @@
$ git pull -q >/dev/null 2>/dev/null
$ cd ..
$ hg commit -m 'git upstream sync'
- committing subrepository $TESTTMP/ta/s
+ committing subrepository s
$ hg debugsub
path s
source ../gitroot
@@ -260,3 +270,37 @@
g
gg
ggg
+
+create nested repo
+
+ $ cd ..
+ $ hg init outer
+ $ cd outer
+ $ echo b>b
+ $ hg add b
+ $ hg commit -m b
+
+ $ hg clone ../t inner
+ updating to branch default
+ cloning subrepo s
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo inner = inner > .hgsub
+ $ hg add .hgsub
+ $ hg commit -m 'nested sub'
+ committing subrepository inner
+
+nested commit
+
+ $ echo ffff >> inner/s/f
+ $ hg status --subrepos
+ M inner/s/f
+ $ hg commit -m nested
+ committing subrepository inner
+ committing subrepository inner/s
+
+nested archive
+
+ $ hg archive --subrepos ../narchive
+ $ ls ../narchive/inner/s
+ f
+ g