Mercurial > hg
changeset 13186:fda7ae939344
merge with crew
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 22 Dec 2010 13:16:00 -0600 |
parents | f16b3b1a2234 (diff) c6e00dfcdcb8 (current diff) |
children | e3b87fb34d00 |
files | |
diffstat | 16 files changed, 819 insertions(+), 356 deletions(-) [+] |
line wrap: on
line diff
--- 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