summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/pseudo
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2012-03-27 16:57:30 -0500
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-03-28 10:10:56 +0100
commitc718c10b4b323bdae9f788300110111d61b0d1a3 (patch)
treebf1e9b92f6d553d0a18312da6e75972eae360f06 /meta/recipes-devtools/pseudo
parent0ba97b4274d576196c77668981065d1b8fe74f45 (diff)
downloadpoky-c718c10b4b323bdae9f788300110111d61b0d1a3.tar.gz
Pseudo: Update to 1.3
The various local patches have made it into upstream, so we update the build files and jump to pseudo 1.3. This also includes a popen() fix which fixes some edge cases that caused failures trying to check git branches and the like. [Yocto bug #2181] (From OE-Core rev: 0b007519fcfb1bcf2be9cad40b0f6265f8798518) Signed-off-by: Seebs <peter.seebach@windriver.com> Updated the pseudo_git.bb to match. Signed-off-by: Mark Hatle <mark.hatle@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/pseudo')
-rw-r--r--meta/recipes-devtools/pseudo/pseudo.inc4
-rw-r--r--meta/recipes-devtools/pseudo/pseudo/oe-config.patch58
-rw-r--r--meta/recipes-devtools/pseudo/pseudo/opendir.patch94
-rw-r--r--meta/recipes-devtools/pseudo/pseudo/renameat.patch229
-rw-r--r--meta/recipes-devtools/pseudo/pseudo/static_sqlite.patch17
-rw-r--r--meta/recipes-devtools/pseudo/pseudo_1.2.bb12
-rw-r--r--meta/recipes-devtools/pseudo/pseudo_1.3.bb8
-rw-r--r--meta/recipes-devtools/pseudo/pseudo_git.bb10
8 files changed, 14 insertions, 418 deletions
diff --git a/meta/recipes-devtools/pseudo/pseudo.inc b/meta/recipes-devtools/pseudo/pseudo.inc
index 4a3ef6f1ce..664a9b5937 100644
--- a/meta/recipes-devtools/pseudo/pseudo.inc
+++ b/meta/recipes-devtools/pseudo/pseudo.inc
@@ -29,9 +29,9 @@ NO32LIBS ??= "0"
29# Compile for the local machine arch... 29# Compile for the local machine arch...
30do_compile () { 30do_compile () {
31 if [ "${SITEINFO_BITS}" == "64" ]; then 31 if [ "${SITEINFO_BITS}" == "64" ]; then
32 ${S}/configure --prefix=${prefix} --libdir=${prefix}/lib/pseudo/lib${SITEINFO_BITS} --with-sqlite=${STAGING_DIR_TARGET}${exec_prefix} --bits=${SITEINFO_BITS} 32 ${S}/configure --prefix=${prefix} --libdir=${prefix}/lib/pseudo/lib${SITEINFO_BITS} --with-sqlite=${STAGING_DIR_TARGET}${exec_prefix} --bits=${SITEINFO_BITS} --enable-static-sqlite
33 else 33 else
34 ${S}/configure --prefix=${prefix} --libdir=${prefix}/lib/pseudo/lib --with-sqlite=${STAGING_DIR_TARGET}${exec_prefix} --bits=${SITEINFO_BITS} 34 ${S}/configure --prefix=${prefix} --libdir=${prefix}/lib/pseudo/lib --with-sqlite=${STAGING_DIR_TARGET}${exec_prefix} --bits=${SITEINFO_BITS} --enable-static-sqlite
35 fi 35 fi
36 oe_runmake ${MAKEOPTS} 36 oe_runmake ${MAKEOPTS}
37} 37}
diff --git a/meta/recipes-devtools/pseudo/pseudo/oe-config.patch b/meta/recipes-devtools/pseudo/pseudo/oe-config.patch
deleted file mode 100644
index d368281ce5..0000000000
--- a/meta/recipes-devtools/pseudo/pseudo/oe-config.patch
+++ /dev/null
@@ -1,58 +0,0 @@
1configure: Fix configuration to match OE-Core requirements
2
3In OE-Core we need to be able to configure for both 32-bit and 64-bit libpseudo
4libraries. In order to avoid some complex manipulations, we adjust the configure
5and Makefile to facilitate this.
6
7Upstream-Status: Submitted
8
9Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
10
11diff --git a/Makefile.in b/Makefile.in
12index 6c57d43..342d066 100644
13--- a/Makefile.in
14+++ b/Makefile.in
15@@ -27,7 +27,7 @@ MARK64=@MARK64@
16 RPATH=@RPATH@
17 VERSION=1.1.1
18
19-LIB=$(shell basename $(LIBDIR))
20+LIB=@LIB@
21 BIN=bin
22 LOCALSTATE=var/pseudo
23 BINDIR=$(PREFIX)/$(BIN)
24diff --git a/configure b/configure
25index 9a480fb..eeb19f3 100755
26--- a/configure
27+++ b/configure
28@@ -80,14 +80,18 @@ if [ -z "$opt_prefix" ]; then
29 usage
30 fi
31
32-if [ -n "$opt_bits" ] && [ -n "$opt_libdir" ]; then
33- echo >&2 "Can not specify both --libdir and --bits"
34- exit 1
35-fi
36 if [ -z "$opt_libdir" ]; then
37 opt_libdir=$opt_prefix/lib$opt_mark64
38 fi
39
40+# We need to find the libdir relative to the prefix, this is required
41+# by the code in pseudo-utils.c that handles relocation.
42+opt_lib=${opt_libdir#$opt_prefix/}
43+if [ "$opt_lib" = "$opt_libdir" ]; then
44+ echo >&2 "libdir must be relative to prefix."
45+ exit 1
46+fi
47+
48 if [ ! -f "${opt_sqlite}/include/sqlite3.h" ]; then
49 echo >&2 "SQLite3 headers not found in at ${opt_sqlite}/include/sqlite3.h. Please check that SQLite3 and SQLite3 headers are installed."
50 exit 1
51@@ -107,6 +111,7 @@ fi
52 sed -e '
53 s,@PREFIX@,'"$opt_prefix"',g
54 s,@LIBDIR@,'"$opt_libdir"',g
55+ s,@LIB@,'"$opt_lib"',g
56 s,@SUFFIX@,'"$opt_suffix"',g
57 s,@SQLITE@,'"$opt_sqlite"',g
58 s!@RPATH@!'"$opt_rpath"'!g
diff --git a/meta/recipes-devtools/pseudo/pseudo/opendir.patch b/meta/recipes-devtools/pseudo/pseudo/opendir.patch
deleted file mode 100644
index bc6cec8e7e..0000000000
--- a/meta/recipes-devtools/pseudo/pseudo/opendir.patch
+++ /dev/null
@@ -1,94 +0,0 @@
1commit 162f2692c399b93311652201a940fdaf9c9e6924
2Author: Peter Seebach <peter.seebach@windriver.com>
3Date: Thu Feb 2 11:45:42 2012 -0600
4
5 Make opendir/closedir stash and forget directory names.
6
7 The dirfd(DIR *) interface allows you to get the fd for a DIR *,
8 meaning you can use it with openat(), meaning you can need its
9 path. This causes a segfault. Also gonna fix the base_path
10 code not to segfault in that case, but first fix the underlying
11 problem.
12
13Upstream-Status: Backport
14
15diff --git a/ChangeLog.txt b/ChangeLog.txt
16index 4de488c..9625b38 100644
17--- a/ChangeLog.txt
18+++ b/ChangeLog.txt
19@@ -1,3 +1,7 @@
20+2012-02-02:
21+ * (seebs) stash dir name for DIR * from opendir using dirfd.
22+ * (seebs) add closedir.
23+
24 2011-11-02:
25 * (seebs) Call this 1.2 because the UNLOAD change is moderately
26 significant, and so's the clone change.
27diff --git a/ports/unix/guts/closedir.c b/ports/unix/guts/closedir.c
28new file mode 100644
29index 0000000..1085361
30--- /dev/null
31+++ b/ports/unix/guts/closedir.c
32@@ -0,0 +1,20 @@
33+/*
34+ * Copyright (c) 2012 Wind River Systems; see
35+ * guts/COPYRIGHT for information.
36+ *
37+ * static int
38+ * wrap_closedir(DIR *dirp) {
39+ * int rc = -1;
40+ */
41+ if (!dirp) {
42+ errno = EFAULT;
43+ return -1;
44+ }
45+
46+ int fd = dirfd(dirp);
47+ pseudo_client_op(OP_CLOSE, 0, fd, -1, 0, 0);
48+ rc = real_closedir(dirp);
49+
50+/* return rc;
51+ * }
52+ */
53diff --git a/ports/unix/guts/opendir.c b/ports/unix/guts/opendir.c
54index 8eaa71f..e69717e 100644
55--- a/ports/unix/guts/opendir.c
56+++ b/ports/unix/guts/opendir.c
57@@ -6,8 +6,25 @@
58 * wrap_opendir(const char *path) {
59 * DIR * rc = NULL;
60 */
61+ struct stat buf;
62+ int save_errno;
63
64 rc = real_opendir(path);
65+ if (rc) {
66+ int fd;
67+ save_errno = errno;
68+ fd = dirfd(rc);
69+ if (real_fstat(fd, &buf) == -1) {
70+ pseudo_debug(1, "diropen (fd %d) succeeded, but fstat failed (%s).\n",
71+ fd, strerror(errno));
72+ pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, 0);
73+ } else {
74+ pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, &buf);
75+ }
76+
77+
78+ errno = save_errno;
79+ }
80
81 /* return rc;
82 * }
83diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in
84index e06e404..32250c4 100644
85--- a/ports/unix/wrapfuncs.in
86+++ b/ports/unix/wrapfuncs.in
87@@ -21,6 +21,7 @@ long pathconf(const char *path, int name);
88 char *realpath(const char *name, char *resolved_name); /* version="GLIBC_2.3" */
89 int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
90 DIR *opendir(const char *path);
91+int closedir(DIR *dirp);
92 char *tempnam(const char *template, const char *pfx);
93 char *tmpnam(char *s);
94 int truncate(const char *path, off_t length);
diff --git a/meta/recipes-devtools/pseudo/pseudo/renameat.patch b/meta/recipes-devtools/pseudo/pseudo/renameat.patch
deleted file mode 100644
index a2b2cbc78c..0000000000
--- a/meta/recipes-devtools/pseudo/pseudo/renameat.patch
+++ /dev/null
@@ -1,229 +0,0 @@
1commit 795f2b44b7f692151556782f142a4a6e7d45d892
2Author: Peter Seebach <peter.seebach@windriver.com>
3Date: Thu Feb 2 15:49:21 2012 -0600
4
5 Implement renameat()
6
7 After three long years, someone tried to use this. This was impossibly
8 hard back when pseudo was written, because there was only one dirfd
9 provided for. Thing is, now, the canonicalization happens in wrapfuncs,
10 so a small tweak to makewrappers to recognize that oldpath should use
11 olddirfd if it exists is enough to get us fully canonicalized paths
12 when needed.
13
14 Also fix the crash if base_path gets called with an fd for which we have
15 no path.
16
17Upstream-Status: Backport
18
19diff --git a/ChangeLog.txt b/ChangeLog.txt
20index 9625b38..25bd463 100644
21--- a/ChangeLog.txt
22+++ b/ChangeLog.txt
23@@ -1,6 +1,9 @@
24 2012-02-02:
25 * (seebs) stash dir name for DIR * from opendir using dirfd.
26 * (seebs) add closedir.
27+ * (seebs) add initial pass at renameat()
28+ * (seebs) in base_path, don't try to strlen the result if
29+ fd_path() returns NULL.
30
31 2011-11-02:
32 * (seebs) Call this 1.2 because the UNLOAD change is moderately
33diff --git a/makewrappers b/makewrappers
34index 20bbf2b..bf344d6 100755
35--- a/makewrappers
36+++ b/makewrappers
37@@ -211,12 +211,13 @@ class Function:
38 self.flags = '0'
39 self.port = port
40 self.directory = ''
41- self.version = 'NULL'
42+ self.version = 'NULL'
43 # On Darwin, some functions are SECRETLY converted to foo$INODE64
44 # when called. So we have to look those up for real_*
45 self.inode64 = None
46 self.real_func = None
47 self.paths_to_munge = []
48+ self.dirfds = {}
49 self.hand_wrapped = None
50 # used for the copyright date when creating stub functions
51 self.date = datetime.date.today().year
52@@ -239,6 +240,7 @@ class Function:
53 # * If the arg has a name ending in 'path', we will canonicalize it.
54 # * If the arg is named 'dirfd' or 'flags', it becomes the default
55 # values for the dirfd and flags arguments when canonicalizing.
56+ # * If the name ends in dirfd, we do the same fancy stuff.
57 # * Note that the "comments" field (/* ... */ after the decl) can
58 # override the dirfd/flags values.
59 self.args = ArgumentList(bits.group(2))
60@@ -246,7 +248,9 @@ class Function:
61 # ignore varargs, they never get these special treatments
62 if arg.vararg:
63 pass
64- elif arg.name == 'dirfd':
65+ elif arg.name[-5:] == 'dirfd':
66+ if len(arg.name) > 5:
67+ self.dirfds[arg.name[:-5]] = True
68 self.dirfd = 'dirfd'
69 elif arg.name == 'flags':
70 self.flags = 'flags'
71@@ -325,9 +329,13 @@ class Function:
72 """create/allocate canonical paths"""
73 alloc_paths = []
74 for path in self.paths_to_munge:
75+ prefix = path[:-4]
76+ if not prefix in self.dirfds:
77+ prefix = ''
78+ print "for path %s: prefix <%s>" % ( path, prefix )
79 alloc_paths.append(
80- "%s = pseudo_root_path(__func__, __LINE__, %s, %s, %s);" %
81- (path, self.dirfd, path, self.flags))
82+ "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
83+ (path, prefix, self.dirfd, path, self.flags))
84 return "\n\t\t\t".join(alloc_paths)
85
86 def free_paths(self):
87diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c
88index c8203b7..f13cd1e 100644
89--- a/ports/unix/guts/renameat.c
90+++ b/ports/unix/guts/renameat.c
91@@ -1,15 +1,111 @@
92 /*
93- * Copyright (c) 2008-2010 Wind River Systems; see
94+ * Copyright (c) 2008-2012 Wind River Systems; see
95 * guts/COPYRIGHT for information.
96 *
97 * static int
98 * wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
99 * int rc = -1;
100 */
101+ pseudo_msg_t *msg;
102+ struct stat oldbuf, newbuf;
103+ int oldrc, newrc;
104+ int save_errno;
105+ int old_db_entry = 0;
106
107- pseudo_diag("help! unimplemented renameat [%s -> %s].\n", oldpath, newpath);
108+ pseudo_debug(2, "renameat: %d,%s->%d,%s\n",
109+ olddirfd, oldpath ? oldpath : "<nil>",
110+ newdirfd, newpath ? newpath : "<nil>");
111+
112+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
113+ if (olddirfd != AT_FDCWD || newdirfd != AT_FDCWD) {
114+ errno = ENOSYS;
115+ return -1;
116+ }
117+#endif
118+
119+ if (!oldpath || !newpath) {
120+ errno = EFAULT;
121+ return -1;
122+ }
123+
124+ save_errno = errno;
125+
126+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
127+ newrc = real_lstat(newpath, &newbuf);
128+ oldrc = real_lstat(oldpath, &oldbuf);
129+#else
130+ oldrc = real___fxstatat(_STAT_VER, olddirfd, oldpath, &oldbuf, AT_SYMLINK_NOFOLLOW);
131+ newrc = real___fxstatat(_STAT_VER, newdirfd, newpath, &newbuf, AT_SYMLINK_NOFOLLOW);
132+#endif
133+
134+ errno = save_errno;
135+
136+ /* newpath must be removed. */
137+ /* as with unlink, we have to mark that the file may get deleted */
138+ msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, newdirfd, newpath, newrc ? NULL : &newbuf);
139+ if (msg && msg->result == RESULT_SUCCEED)
140+ old_db_entry = 1;
141 rc = real_renameat(olddirfd, oldpath, newdirfd, newpath);
142+ save_errno = errno;
143+ if (old_db_entry) {
144+ if (rc == -1) {
145+ /* since we failed, that wasn't really unlinked -- put
146+ * it back.
147+ */
148+ pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, newdirfd, newpath, &newbuf);
149+ } else {
150+ /* confirm that the file was removed */
151+ pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, newdirfd, newpath, &newbuf);
152+ }
153+ }
154+ if (rc == -1) {
155+ /* and we're done. */
156+ errno = save_errno;
157+ return rc;
158+ }
159+ save_errno = errno;
160+ /* nothing to do for a "rename" of a link to itself */
161+ if (newrc != -1 && oldrc != -1 &&
162+ newbuf.st_dev == oldbuf.st_dev &&
163+ newbuf.st_ino == oldbuf.st_ino) {
164+ return rc;
165+ }
166+
167+ /* rename(3) is not mv(1). rename(file, dir) fails; you must provide
168+ * the corrected path yourself. You can rename over a directory only
169+ * if the source is a directory. Symlinks are simply removed.
170+ *
171+ * If we got here, the real rename call succeeded. That means newpath
172+ * has been unlinked and oldpath has been linked to it.
173+ *
174+ * There are a ton of special cases to error check. I don't check
175+ * for any of them, because in every such case, the underlying rename
176+ * failed, and there is nothing to do.
177+ * The only tricky part is that, because we used to ignore symlinks,
178+ * we may have to rename or remove directory trees even though in
179+ * theory rename can never destroy a directory tree.
180+ */
181+ if (!old_db_entry) {
182+ /* create an entry under the old name, which will then be
183+ * renamed; this way, children would get renamed too, if there
184+ * were any.
185+ */
186+ if (newrc == 0) {
187+ if (newbuf.st_dev != oldbuf.st_dev) {
188+ oldbuf.st_dev = newbuf.st_dev;
189+ oldbuf.st_ino = newbuf.st_ino;
190+ }
191+ }
192+ pseudo_debug(1, "creating new '%s' [%llu] to rename\n",
193+ oldpath, (unsigned long long) oldbuf.st_ino);
194+ pseudo_client_op_plain(OP_LINK, 0, -1, olddirfd, oldpath, &oldbuf);
195+ }
196+ /* special case: use 'fd' for olddirfd, because
197+ * we know it has no other meaning for RENAME
198+ */
199+ pseudo_client_op_plain(OP_RENAME, 0, olddirfd, newdirfd, newpath, &oldbuf, oldpath);
200
201+ errno = save_errno;
202 /* return rc;
203 * }
204 */
205diff --git a/pseudo_client.c b/pseudo_client.c
206index 48607c2..4a30420 100644
207--- a/pseudo_client.c
208+++ b/pseudo_client.c
209@@ -988,6 +988,8 @@ base_path(int dirfd, const char *path, int leave_last) {
210 if (dirfd != -1 && dirfd != AT_FDCWD) {
211 if (dirfd >= 0) {
212 basepath = fd_path(dirfd);
213+ }
214+ if (basepath) {
215 baselen = strlen(basepath);
216 } else {
217 pseudo_diag("got *at() syscall for unknown directory, fd %d\n", dirfd);
218@@ -1128,7 +1130,10 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
219 if (path) {
220 pseudo_debug(2, " %s", path);
221 }
222- if (fd != -1) {
223+ /* for OP_RENAME in renameat, "fd" is also used for the
224+ * second dirfd.
225+ */
226+ if (fd != -1 && op != OP_RENAME) {
227 pseudo_debug(2, " [fd %d]", fd);
228 }
229 if (buf) {
diff --git a/meta/recipes-devtools/pseudo/pseudo/static_sqlite.patch b/meta/recipes-devtools/pseudo/pseudo/static_sqlite.patch
deleted file mode 100644
index f9223a86ae..0000000000
--- a/meta/recipes-devtools/pseudo/pseudo/static_sqlite.patch
+++ /dev/null
@@ -1,17 +0,0 @@
1Due to disabling the LD_LIBRARY_PATH handling, we need to use a static
2libsqlite.
3
4Upstream-Status: Inappropriate [configuration]
5
6diff -ur git.orig/Makefile.in git/Makefile.in
7--- git.orig/Makefile.in
8+++ git/Makefile.in
9@@ -55,7 +55,7 @@
10
11 # needed for anything that links with pseduo_client.o, pretty much
12 CLIENT_LDFLAGS=-ldl -lpthread
13-DB_LDFLAGS=-lsqlite3 -lpthread
14+DB_LDFLAGS=$(SQLITE)/lib/libsqlite3.a -lpthread
15
16 PSEUDO=$(BIN)/pseudo
17 PSEUDODB=$(BIN)/pseudodb
diff --git a/meta/recipes-devtools/pseudo/pseudo_1.2.bb b/meta/recipes-devtools/pseudo/pseudo_1.2.bb
deleted file mode 100644
index 9f95bd7734..0000000000
--- a/meta/recipes-devtools/pseudo/pseudo_1.2.bb
+++ /dev/null
@@ -1,12 +0,0 @@
1require pseudo.inc
2
3PR = "r6"
4
5SRC_URI = "http://www.yoctoproject.org/downloads/${BPN}/${BPN}-${PV}.tar.bz2 \
6 file://oe-config.patch \
7 file://static_sqlite.patch \
8 file://opendir.patch \
9 file://renameat.patch"
10
11SRC_URI[md5sum] = "a2819084bab7e991f06626d02cf55048"
12SRC_URI[sha256sum] = "4749a22df687f44d24c26e97170d4781a1bd52d5ee092364a40877e4d96ff058"
diff --git a/meta/recipes-devtools/pseudo/pseudo_1.3.bb b/meta/recipes-devtools/pseudo/pseudo_1.3.bb
new file mode 100644
index 0000000000..e7a329cea8
--- /dev/null
+++ b/meta/recipes-devtools/pseudo/pseudo_1.3.bb
@@ -0,0 +1,8 @@
1require pseudo.inc
2
3PR = "r7"
4
5SRC_URI = "http://www.yoctoproject.org/downloads/${BPN}/${BPN}-${PV}.tar.bz2"
6
7SRC_URI[md5sum] = "5832bb70e6dce1a17b9b33a9c5c4b923"
8SRC_URI[sha256sum] = "2f30e2e9ec966cec3a321fc2ed80408ee77ad6c0cd73aaf36f88b98e008f8508"
diff --git a/meta/recipes-devtools/pseudo/pseudo_git.bb b/meta/recipes-devtools/pseudo/pseudo_git.bb
index 4f8c9d619a..9414c79b78 100644
--- a/meta/recipes-devtools/pseudo/pseudo_git.bb
+++ b/meta/recipes-devtools/pseudo/pseudo_git.bb
@@ -1,14 +1,12 @@
1require pseudo.inc 1require pseudo.inc
2 2
3SRCREV = "17c2233f93692f79684792750001ee6d13e03925" 3SRCREV = "f0375c9aaefbccfd41aebbf6d332bb4d9e8f980c"
4PV = "1.2+git${SRCPV}" 4PV = "1.3+git${SRCPV}"
5PR = "r21" 5PR = "r22"
6 6
7DEFAULT_PREFERENCE = "-1" 7DEFAULT_PREFERENCE = "-1"
8 8
9SRC_URI = "git://github.com/wrpseudo/pseudo.git;protocol=git \ 9SRC_URI = "git://github.com/wrpseudo/pseudo.git;protocol=git"
10 file://oe-config.patch \
11 file://static_sqlite.patch"
12 10
13S = "${WORKDIR}/git" 11S = "${WORKDIR}/git"
14 12