--- a/i18n/ru.po Fri Aug 17 15:12:01 2012 -0700
+++ b/i18n/ru.po Tue Aug 21 13:12:56 2012 -0700
@@ -173,7 +173,7 @@
msgstr ""
"Project-Id-Version: Mercurial\n"
"Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2012-08-09 13:23+0400\n"
+"POT-Creation-Date: 2012-08-13 16:01+0400\n"
"PO-Revision-Date: 2011-05-12 23:48+0400\n"
"Last-Translator: Alexander Sauta <demosito@gmail.com>\n"
"Language-Team: Russian\n"
@@ -14542,11 +14542,11 @@
" bookmarks`)."
msgid ""
-" Update sets the working directory's parent revison to the specified\n"
+" Update sets the working directory's parent revision to the specified\n"
" changeset (see :hg:`help parents`)."
msgstr ""
-" Update устанавливает ревизию родителя рабочего каталога в заданный\n"
-" набор изменений (см. :hg:`help update`)."
+" Update делает заданный набор изменений родительской ревизией рабочего\n"
+" каталога (см. :hg:`help parents`)."
msgid ""
" If the changeset is not a descendant or ancestor of the working\n"
--- a/mercurial/commands.py Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/commands.py Tue Aug 21 13:12:56 2012 -0700
@@ -1847,14 +1847,17 @@
localrevs = opts.get('local_head')
doit(localrevs, remoterevs)
-@command('debugfileset', [], ('REVSPEC'))
-def debugfileset(ui, repo, expr):
+@command('debugfileset',
+ [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
+ _('[-r REV] FILESPEC'))
+def debugfileset(ui, repo, expr, **opts):
'''parse and apply a fileset specification'''
+ ctx = scmutil.revsingle(repo, opts.get('rev'), None)
if ui.verbose:
tree = fileset.parse(expr)[0]
ui.note(tree, "\n")
- for f in fileset.getfileset(repo[None], expr):
+ for f in fileset.getfileset(ctx, expr):
ui.write("%s\n" % f)
@command('debugfsinfo', [], _('[PATH]'))
@@ -4174,7 +4177,7 @@
res.append(fn[plen:-slen])
finally:
lock.release()
- for f in sorted(res):
+ for f in res:
ui.write("%s\n" % f)
return
--- a/mercurial/fileset.py Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/fileset.py Tue Aug 21 13:12:56 2012 -0700
@@ -107,6 +107,11 @@
s = set(getset(mctx, x))
return [r for r in mctx.subset if r not in s]
+def minusset(mctx, x, y):
+ xl = getset(mctx, x)
+ yl = set(getset(mctx, y))
+ return [f for f in xl if f not in yl]
+
def listset(mctx, a, b):
raise error.ParseError(_("can't use a list in this context"))
@@ -251,8 +256,11 @@
"""``grep(regex)``
File contains the given regular expression.
"""
- pat = getstring(x, _("grep requires a pattern"))
- r = re.compile(pat)
+ try:
+ # i18n: "grep" is a keyword
+ r = re.compile(getstring(x, _("grep requires a pattern")))
+ except re.error, e:
+ raise error.ParseError(_('invalid match pattern: %s') % e)
return [f for f in mctx.existing() if r.search(mctx.ctx[f].data())]
_units = dict(k=2**10, K=2**10, kB=2**10, KB=2**10,
@@ -406,6 +414,7 @@
'symbol': stringset,
'and': andset,
'or': orset,
+ 'minus': minusset,
'list': listset,
'group': getset,
'not': notset,
@@ -424,7 +433,14 @@
def filter(self, files):
return [f for f in files if f in self.subset]
def existing(self):
- return (f for f in self.subset if f in self.ctx)
+ if self._status is not None:
+ removed = set(self._status[3])
+ unknown = set(self._status[4] + self._status[5])
+ else:
+ removed = set()
+ unknown = set()
+ return (f for f in self.subset
+ if (f in self.ctx and f not in removed) or f in unknown)
def narrow(self, files):
return matchctx(self.ctx, self.filter(files), self._status)
@@ -438,14 +454,26 @@
return True
return False
+# filesets using matchctx.existing()
+_existingcallers = [
+ 'binary',
+ 'exec',
+ 'grep',
+ 'size',
+ 'symlink',
+]
+
def getfileset(ctx, expr):
tree, pos = parse(expr)
if (pos != len(expr)):
raise error.ParseError(_("invalid token"), pos)
# do we need status info?
- if _intree(['modified', 'added', 'removed', 'deleted',
- 'unknown', 'ignored', 'clean'], tree):
+ if (_intree(['modified', 'added', 'removed', 'deleted',
+ 'unknown', 'ignored', 'clean'], tree) or
+ # Using matchctx.existing() on a workingctx requires us to check
+ # for deleted files.
+ (ctx.rev() is None and _intree(_existingcallers, tree))):
unknown = _intree(['unknown'], tree)
ignored = _intree(['ignored'], tree)
@@ -457,7 +485,7 @@
subset.extend(c)
else:
status = None
- subset = ctx.walk(ctx.match([]))
+ subset = list(ctx.walk(ctx.match([])))
return getset(matchctx(ctx, subset, status), tree)
--- a/mercurial/localrepo.py Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/localrepo.py Tue Aug 21 13:12:56 2012 -0700
@@ -1009,7 +1009,7 @@
util.rename(self.join('undo.dirstate'), self.join('dirstate'))
try:
branch = self.opener.read('undo.branch')
- self.dirstate.setbranch(branch)
+ self.dirstate.setbranch(encoding.tolocal(branch))
except IOError:
ui.warn(_('named branch could not be reset: '
'current branch is still \'%s\'\n')
@@ -1312,6 +1312,7 @@
matched = set(changes[0] + changes[1] + changes[2])
for f in match.files():
+ f = self.dirstate.normalize(f)
if f == '.' or f in matched or f in wctx.substate:
continue
if f in changes[3]: # missing
--- a/mercurial/parsers.c Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/parsers.c Tue Aug 21 13:12:56 2012 -0700
@@ -9,6 +9,7 @@
#include <Python.h>
#include <ctype.h>
+#include <stddef.h>
#include <string.h>
#include "util.h"
@@ -72,7 +73,7 @@
for (start = cur = str, zero = NULL; cur < str + len; cur++) {
PyObject *file = NULL, *node = NULL;
PyObject *flags = NULL;
- int nlen;
+ ptrdiff_t nlen;
if (!*cur) {
zero = cur;
@@ -94,7 +95,7 @@
nlen = cur - zero - 1;
- node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
+ node = unhexlify(zero + 1, nlen > 40 ? 40 : (int)nlen);
if (!node)
goto bail;
@@ -1084,8 +1085,10 @@
return NULL;
}
- if (nodelen > 40)
- nodelen = 40;
+ if (nodelen > 40) {
+ PyErr_SetString(PyExc_ValueError, "key too long");
+ return NULL;
+ }
for (i = 0; i < nodelen; i++)
hexdigit(node, i);
--- a/mercurial/store.py Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/store.py Tue Aug 21 13:12:56 2012 -0700
@@ -7,7 +7,7 @@
from i18n import _
import osutil, scmutil, util
-import os, stat
+import os, stat, errno
_sha = util.sha1
@@ -398,12 +398,14 @@
def datafiles(self):
rewrite = False
existing = []
- for f in self.fncache:
+ for f in sorted(self.fncache):
ef = self.encode(f)
try:
yield f, ef, self.getsize(ef)
existing.append(f)
- except OSError:
+ except OSError, err:
+ if err.errno != errno.ENOENT:
+ raise
# nonexistent entry
rewrite = True
if rewrite:
--- a/mercurial/templatekw.py Fri Aug 17 15:12:01 2012 -0700
+++ b/mercurial/templatekw.py Tue Aug 21 13:12:56 2012 -0700
@@ -275,6 +275,28 @@
"""
return ctx.hex()
+def showp1rev(repo, ctx, templ, **args):
+ """:p1rev: Integer. The repository-local revision number of the changeset's
+ first parent, or -1 if the changeset has no parents."""
+ return ctx.p1().rev()
+
+def showp2rev(repo, ctx, templ, **args):
+ """:p2rev: Integer. The repository-local revision number of the changeset's
+ second parent, or -1 if the changeset has no second parent."""
+ return ctx.p2().rev()
+
+def showp1node(repo, ctx, templ, **args):
+ """:p1node: String. The identification hash of the changeset's first parent,
+ as a 40 digit hexadecimal string. If the changeset has no parents, all
+ digits are 0."""
+ return ctx.p1().hex()
+
+def showp2node(repo, ctx, templ, **args):
+ """:p2node: String. The identification hash of the changeset's second
+ parent, as a 40 digit hexadecimal string. If the changeset has no second
+ parent, all digits are 0."""
+ return ctx.p2().hex()
+
def showphase(repo, ctx, templ, **args):
""":phase: String. The changeset phase name."""
return ctx.phasestr()
@@ -320,6 +342,10 @@
'latesttagdistance': showlatesttagdistance,
'manifest': showmanifest,
'node': shownode,
+ 'p1rev': showp1rev,
+ 'p1node': showp1node,
+ 'p2rev': showp2rev,
+ 'p2node': showp2node,
'phase': showphase,
'phaseidx': showphaseidx,
'rev': showrev,
--- a/tests/test-cat.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-cat.t Tue Aug 21 13:12:56 2012 -0700
@@ -21,3 +21,14 @@
[1]
$ hg cat -r 1 b
1
+
+Test fileset
+
+ $ echo 3 > c
+ $ hg ci -Am addmore c
+ $ hg cat 'set:not(b) or a'
+ 3
+ $ hg cat 'set:c or b'
+ 1
+ 3
+
--- a/tests/test-command-template.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-command-template.t Tue Aug 21 13:12:56 2012 -0700
@@ -592,7 +592,8 @@
$ for key in author branch branches date desc file_adds file_dels file_mods \
> file_copies file_copies_switch files \
- > manifest node parents rev tags diffstat extras; do
+ > manifest node parents rev tags diffstat extras \
+ > p1rev p2rev p1node p2node; do
> for mode in '' --verbose --debug; do
> hg log $mode --template "$key$mode: {$key}\n"
> done
@@ -1095,7 +1096,114 @@
extras--debug: branch=default
extras--debug: branch=default
extras--debug: branch=default
-
+ p1rev: 7
+ p1rev: -1
+ p1rev: 5
+ p1rev: 3
+ p1rev: 3
+ p1rev: 2
+ p1rev: 1
+ p1rev: 0
+ p1rev: -1
+ p1rev--verbose: 7
+ p1rev--verbose: -1
+ p1rev--verbose: 5
+ p1rev--verbose: 3
+ p1rev--verbose: 3
+ p1rev--verbose: 2
+ p1rev--verbose: 1
+ p1rev--verbose: 0
+ p1rev--verbose: -1
+ p1rev--debug: 7
+ p1rev--debug: -1
+ p1rev--debug: 5
+ p1rev--debug: 3
+ p1rev--debug: 3
+ p1rev--debug: 2
+ p1rev--debug: 1
+ p1rev--debug: 0
+ p1rev--debug: -1
+ p2rev: -1
+ p2rev: -1
+ p2rev: 4
+ p2rev: -1
+ p2rev: -1
+ p2rev: -1
+ p2rev: -1
+ p2rev: -1
+ p2rev: -1
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--verbose: 4
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--verbose: -1
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p2rev--debug: 4
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p2rev--debug: -1
+ p1node: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
+ p1node: 0000000000000000000000000000000000000000
+ p1node: 13207e5a10d9fd28ec424934298e176197f2c67f
+ p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node: 97054abb4ab824450e9164180baf491ae0078465
+ p1node: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+ p1node: 1e4e1b8f71e05681d422154f5421e385fec3454f
+ p1node: 0000000000000000000000000000000000000000
+ p1node--verbose: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
+ p1node--verbose: 0000000000000000000000000000000000000000
+ p1node--verbose: 13207e5a10d9fd28ec424934298e176197f2c67f
+ p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node--verbose: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node--verbose: 97054abb4ab824450e9164180baf491ae0078465
+ p1node--verbose: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+ p1node--verbose: 1e4e1b8f71e05681d422154f5421e385fec3454f
+ p1node--verbose: 0000000000000000000000000000000000000000
+ p1node--debug: 29114dbae42b9f078cf2714dbe3a86bba8ec7453
+ p1node--debug: 0000000000000000000000000000000000000000
+ p1node--debug: 13207e5a10d9fd28ec424934298e176197f2c67f
+ p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node--debug: 10e46f2dcbf4823578cf180f33ecf0b957964c47
+ p1node--debug: 97054abb4ab824450e9164180baf491ae0078465
+ p1node--debug: b608e9d1a3f0273ccf70fb85fd6866b3482bf965
+ p1node--debug: 1e4e1b8f71e05681d422154f5421e385fec3454f
+ p1node--debug: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: bbe44766e73d5f11ed2177f1838de10c53ef3e74
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: bbe44766e73d5f11ed2177f1838de10c53ef3e74
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--verbose: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: bbe44766e73d5f11ed2177f1838de10c53ef3e74
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
+ p2node--debug: 0000000000000000000000000000000000000000
Filters work:
--- a/tests/test-debugcomplete.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-debugcomplete.t Tue Aug 21 13:12:56 2012 -0700
@@ -229,7 +229,7 @@
debugdata: changelog, manifest
debugdate: extended
debugdiscovery: old, nonheads, ssh, remotecmd, insecure
- debugfileset:
+ debugfileset: rev
debugfsinfo:
debuggetbundle: head, common, type
debugignore:
--- a/tests/test-encoding.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-encoding.t Tue Aug 21 13:12:56 2012 -0700
@@ -44,6 +44,10 @@
marked working directory as branch \xe9 (esc)
(branches are permanent and global, did you want a bookmark?)
$ HGENCODING=latin-1 hg ci -m 'latin1 branch'
+ $ hg -q rollback
+ $ HGENCODING=latin-1 hg branch
+ \xe9 (esc)
+ $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
$ rm .hg/branch
hg log (ascii)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-fileset.t Tue Aug 21 13:12:56 2012 -0700
@@ -0,0 +1,228 @@
+ $ fileset() {
+ > hg debugfileset "$@"
+ > }
+
+ $ hg init repo
+ $ cd repo
+ $ echo a > a1
+ $ echo a > a2
+ $ echo b > b1
+ $ echo b > b2
+ $ hg ci -Am addfiles
+ adding a1
+ adding a2
+ adding b1
+ adding b2
+
+Test operators and basic patterns
+
+ $ fileset a1
+ a1
+ $ fileset 'a*'
+ a1
+ a2
+ $ fileset '"re:a\d"'
+ a1
+ a2
+ $ fileset 'a1 or a2'
+ a1
+ a2
+ $ fileset 'a1 | a2'
+ a1
+ a2
+ $ fileset 'a* and "*1"'
+ a1
+ $ fileset 'a* & "*1"'
+ a1
+ $ fileset 'not (r"a*")'
+ b1
+ b2
+ $ fileset '! ("a*")'
+ b1
+ b2
+ $ fileset 'a* - a1'
+ a2
+
+Test files status
+
+ $ rm a1
+ $ hg rm a2
+ $ echo b >> b2
+ $ hg cp b1 c1
+ $ echo c > c2
+ $ echo c > c3
+ $ cat > .hgignore <<EOF
+ > \.hgignore
+ > 2$
+ > EOF
+ $ fileset 'modified()'
+ b2
+ $ fileset 'added()'
+ c1
+ $ fileset 'removed()'
+ a2
+ $ fileset 'deleted()'
+ a1
+ $ fileset 'unknown()'
+ c3
+ $ fileset 'ignored()'
+ .hgignore
+ c2
+ $ fileset 'hgignore()'
+ a2
+ b2
+ $ fileset 'clean()'
+ b1
+ $ fileset 'copied()'
+ c1
+
+Test files properties
+
+ >>> file('bin', 'wb').write('\0a')
+ $ fileset 'binary()'
+ $ fileset 'binary() and unknown()'
+ bin
+ $ echo '^bin$' >> .hgignore
+ $ fileset 'binary() and ignored()'
+ bin
+ $ hg add bin
+ $ fileset 'binary()'
+ bin
+
+ $ fileset 'grep("b{1}")'
+ b2
+ c1
+ b1
+ $ fileset 'grep("missingparens(")'
+ hg: parse error: invalid match pattern: unbalanced parenthesis
+ [255]
+
+#if execbit
+ $ chmod +x b2
+ $ fileset 'exec()'
+ b2
+#endif
+
+#if symlink
+ $ ln -s b2 b2link
+ $ fileset 'symlink() and unknown()'
+ b2link
+ $ hg add b2link
+#endif
+
+ >>> file('1k', 'wb').write(' '*1024)
+ >>> file('2k', 'wb').write(' '*2048)
+ $ hg add 1k 2k
+ $ fileset 'size("bar")'
+ hg: parse error: couldn't parse size: bar
+ [255]
+ $ fileset 'size(1k)'
+ 1k
+ $ fileset '(1k or 2k) and size("< 2k")'
+ 1k
+ $ fileset '(1k or 2k) and size("<=2k")'
+ 1k
+ 2k
+ $ fileset '(1k or 2k) and size("> 1k")'
+ 2k
+ $ fileset '(1k or 2k) and size(">=1K")'
+ 1k
+ 2k
+ $ fileset '(1k or 2k) and size(".5KB - 1.5kB")'
+ 1k
+
+Test merge states
+
+ $ hg ci -m manychanges
+ $ hg up -C 0
+ * files updated, 0 files merged, * files removed, 0 files unresolved (glob)
+ $ echo c >> b2
+ $ hg ci -m diverging b2
+ created new head
+ $ fileset 'resolved()'
+ $ fileset 'unresolved()'
+ $ hg merge
+ merging b2
+ warning: conflicts during merge.
+ merging b2 incomplete! (edit conflicts, then use 'hg resolve --mark')
+ * files updated, 0 files merged, * files removed, 1 files unresolved (glob)
+ use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+ [1]
+ $ fileset 'resolved()'
+ $ fileset 'unresolved()'
+ b2
+ $ echo e > b2
+ $ hg resolve -m b2
+ $ fileset 'resolved()'
+ b2
+ $ fileset 'unresolved()'
+ $ hg ci -m merge
+
+Test subrepo predicate
+
+ $ hg init sub
+ $ echo a > sub/suba
+ $ hg -R sub add sub/suba
+ $ hg -R sub ci -m sub
+ $ echo 'sub = sub' > .hgsub
+ $ fileset 'subrepo()'
+ $ hg add .hgsub
+ $ fileset 'subrepo()'
+ sub
+ $ fileset 'subrepo("sub")'
+ sub
+ $ fileset 'subrepo("glob:*")'
+ sub
+ $ hg ci -m subrepo
+
+Test with a revision
+
+ $ hg log -G --template '{rev} {desc}\n'
+ @ 4 subrepo
+ |
+ o 3 merge
+ |\
+ | o 2 diverging
+ | |
+ o | 1 manychanges
+ |/
+ o 0 addfiles
+
+ $ echo unknown > unknown
+ $ fileset -r1 'modified()'
+ b2
+ $ fileset -r1 'added() and c1'
+ c1
+ $ fileset -r1 'removed()'
+ a2
+ $ fileset -r1 'deleted()'
+ $ fileset -r1 'unknown()'
+ $ fileset -r1 'ignored()'
+ $ fileset -r1 'hgignore()'
+ b2
+ bin
+ $ fileset -r1 'binary()'
+ bin
+ $ fileset -r1 'size(1k)'
+ 1k
+ $ fileset -r3 'resolved()'
+ $ fileset -r3 'unresolved()'
+
+#if execbit
+ $ fileset -r1 'exec()'
+ b2
+#endif
+
+#if symlink
+ $ fileset -r1 'symlink()'
+ b2link
+#endif
+
+ $ fileset -r4 'subrepo("re:su.*")'
+ sub
+ $ fileset -r4 'subrepo("sub")'
+ sub
+ $ fileset -r4 'b2 or c1'
+ b2
+ c1
+
--- a/tests/test-status.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-status.t Tue Aug 21 13:12:56 2012 -0700
@@ -330,4 +330,9 @@
$ hg status -A --rev 1 1
R 1/2/3/4/5/b.txt
+#if windows
+ $ hg --config ui.slash=false status -A --rev 1 1
+ R 1\2\3\4\5\b.txt
+#endif
+
$ cd ..
--- a/tests/test-template-engine.t Fri Aug 17 15:12:01 2012 -0700
+++ b/tests/test-template-engine.t Tue Aug 21 13:12:56 2012 -0700
@@ -36,4 +36,12 @@
$ hg log --style=./mymap
0 97e5f848f0936960273bbf75be6388cd0350a32b test
+ $ cat > changeset.txt << EOF
+ > {{p1rev}} {{p1node}} {{p2rev}} {{p2node}}
+ > EOF
+ $ hg ci -Ama
+ $ hg log --style=./mymap
+ 0 97e5f848f0936960273bbf75be6388cd0350a32b -1 0000000000000000000000000000000000000000
+ -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000
+
$ cd ..