{"thread":{"id":"639","subject":"[PATCH 1/2] Introduce git-run-with-user-path helper program.","startedAt":"2005-05-16T06:05:19Z","lastAt":"2005-05-19T20:35:29Z","messageCount":15,"participants":["Junio C Hamano","Petr Baudis","Linus Torvalds","Thomas Glanzmann"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"3406","messageId":"7voebbpuxs.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":null,"subject":"[PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-16T06:05:19Z","receivedAt":"2005-05-16T06:05:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Introduce git-run-with-user-path helper program.\n\nA new command git-run-with-user-path takes a command and paths\nthat are filesystem paths (either relative to the cwd or\nabsolute pathname).  It canonicalizes these paths to be usable\nby the core GIT commands, filters using the ignore pattern rule,\nchdir(2)'s to the top level of the tree and runs the given\ncommand with these canonicalizd paths as its arguments.\n\nThis version contains necessary hooks to implement the ignore\npattern rule, but it does not implement any ignore pattern\nrules, waiting for more mailing list discussions.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\nDocumentation/git-run-with-user-path.txt |   79 ++++++++++++\nMakefile                                 |    7 -\npaths.c                                  |  199 +++++++++++++++++++++++++++++++\npaths.h                                  |   14 ++\nrun-with-user-path.c                     |   61 +++++++++\nt/README                                 |    1 \nt/t7000-git-run-with-user-path-basic.sh  |   66 ++++++++++\nupdate-cache.c                           |   29 ----\n8 files changed, 427 insertions(+), 29 deletions(-)\nDocumentation/git-run-with-user-path.txt (. --> 100644)\npaths.c (. --> 100644)\npaths.h (. --> 100644)\nrun-with-user-path.c (. --> 100644)\nt/t7000-git-run-with-user-path-basic.sh (. --> 100755)\n\n--- a/Documentation/git-run-with-user-path.txt\n+++ b/Documentation/git-run-with-user-path.txt\n@@ -0,0 +1,79 @@\n+git-run-with-user-path(1)\n+=========================\n+v0.1, May 2005\n+\n+NAME\n+----\n+git-run-with-user-path - Run command from the top after canonicalizing paths.\n+\n+\n+SYNOPSIS\n+--------\n+'git-run-with-user-path' [options] <command> <argument>... '--' <path>...\n+\n+DESCRIPTION\n+-----------\n+This command takes a <command>, zero or more <argument> and zero\n+or more <path> arguments.  <path> arguments name objects on the\n+filesystem, <command> is typically a core GIT command, and\n+<argument> are the initial arguments to the <command>.\n+\n+It first finds the project top directory (the directory that corresponds\n+to the top of the tree structure GIT_INDEX_FILE describes).  When the\n+environment variable GIT_PROJECT_TOP is set, the value of the variable\n+is used.  Then the <path> parameters are canonicalized to be relative to\n+the project top.  It then chdir(2)'s to the project top directory and\n+runs the given <command>, with <argument> and these canonicalized <path>\n+arguments.\n+\n+This is useful for the Porcelain layer to run core GIT commands from\n+subdirectories.  For example, if linux-2.6.git tree is checked out in\n+/usr/src/linux, you can do:\n+\n+    $ cd /usr/src/linux/fs\n+    $ ... work in fs directory making changes ...\n+    $ git-run-with-user-path git-diff-tree -r HEAD -- ext? ../include/linux\n+    $ find ext? ../include/linux ! -type d -print0 |\n+      xargs -0 git-run-with-user-path git-update-cache --add -- --\n+\n+The above is roughly equivalent to:\n+\n+    $ cd /usr/src/linux\n+    $ git-diff-tree -r HEAD fs/ext? include/linux\n+    $ find fs/ext? include/linux ! -type d -print0 |\n+      xargs git-update-cache --add --\n+\n+\n+OPTIONS\n+-------\n+--no-ignore::\n+\n+\tBy default, the path arguments are filtered with the\n+\tsame ignore rules Porcelain layers use.  With\n+\t--no-ignore flag, there is no such filtering done.\n+\n+\n+ENVIRONMENT VARIABLES\n+---------------------\n+\n+'GIT_PROJECT_TOP'::\n+\tIf the 'GIT_PROJECT_TOP' environment variable is set\n+\tthen it specifies the directory that corresponds to the\n+\ttop level of the tree structure GIT_INDEX_FILE describes.\n+\tWhen this environment variable is not defined, the\n+\tclosest parent directory that has .git/ subdirectory in\n+\tit is looked for and used.\n+\n+\n+Author\n+------\n+Written by Junio C Hamano <junkio@cox.net>\n+\n+Documentation\n+--------------\n+Documentation by Junio C Hamano.\n+\n+GIT\n+---\n+Part of the link:git.html[git] suite\n+\n--- a/Makefile\n+++ b/Makefile\n@@ -28,7 +28,7 @@\n \tgit-unpack-file git-export git-diff-cache git-convert-cache \\\n \tgit-http-pull git-rpush git-rpull git-rev-list git-mktag \\\n \tgit-diff-helper git-tar-tree git-local-pull git-write-blob \\\n-\tgit-get-tar-commit-id\n+\tgit-get-tar-commit-id git-run-with-user-path\n \n all: $(PROG)\n \n@@ -46,6 +46,9 @@\n LIB_H += diff.h\n LIB_OBJS += diff.o\n \n+LIB_H += paths.h\n+LIB_OBJS += paths.o\n+\n LIB_OBJS += gitenv.o\n \n LIBS = $(LIB_FILE)\n@@ -100,6 +103,7 @@\n git-rpush: rsh.c\n git-rpull: rsh.c pull.c\n git-rev-list: rev-list.c\n+git-run-with-user-path: run-with-user-path.c \n git-mktag: mktag.c\n git-diff-helper: diff-helper.c\n git-tar-tree: tar-tree.c\n@@ -117,6 +121,7 @@\n sha1_file.o: $(LIB_H)\n usage.o: $(LIB_H)\n diff.o: $(LIB_H)\n+paths.o: $(LIB_H)\n strbuf.o: $(LIB_H)\n gitenv.o: $(LIB_H)\n \n--- a/paths.c\n+++ b/paths.c\n@@ -0,0 +1,199 @@\n+/*\n+ * Copyright (c) 2005 Junio C Hamano\n+ */\n+#include <string.h>\n+#include \"cache.h\"\n+#include \"paths.h\"\n+\n+/****************************************************************/\n+\n+/* Ignore list handling part */\n+\n+/*\n+ * We fundamentally don't like some paths: we don't want\n+ * dot or dot-dot anywhere, and in fact, we don't even want\n+ * any other dot-files (.git or anything else). They\n+ * are hidden, for chist sake.\n+ *\n+ * Also, we don't want double slashes or slashes at the\n+ * end that can make pathnames ambiguous.\n+ */\n+int verify_path(const char *path)\n+{\n+\tchar c;\n+\n+\tgoto inside;\n+\tfor (;;) {\n+\t\tif (!c)\n+\t\t\treturn 1;\n+\t\tif (c == '/') {\n+inside:\n+\t\t\tc = *path++;\n+\t\t\tif (c != '/' && c != '.' && c != '\\0')\n+\t\t\t\tcontinue;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tc = *path++;\n+\t}\n+}\n+\n+static int initialize_ignore_list(void)\n+{\n+\t/* Put the Porcelain layer ignore logic initialization here.\n+\t * Return non-zero after issuing appropriate error message\n+\t * if initialization fails.\n+\t */\n+\treturn 0;\n+}\n+\n+int path_ignored(const char *path)\n+{\n+\tif (!verify_path(path))\n+\t\treturn 1;\n+\n+\t/* Put the Porcelain layer ignore logic here.\n+\t * Return non-zero if path is to be ignored.\n+\t */\n+\treturn 0;\n+}\n+\n+\n+/****************************************************************/\n+\n+/* Path canonicalization part */\n+\n+char *git_project_top = NULL;\n+static char git_cwd[PATH_MAX];\n+\n+static int find_project_top(void)\n+{\n+\tchar path[PATH_MAX];\n+\tint dir_length;\n+\n+\tif (!getcwd(git_cwd, sizeof(git_cwd)))\n+\t\treturn error(\"cannot get cwd to find GIT_PROJECT_TOP\");\n+\n+\tgit_project_top = gitenv(\"GIT_PROJECT_TOP\");\n+\tif (git_project_top)\n+\t\treturn 0;\n+\n+\tstrcpy(path, git_cwd);\n+\twhile (path[0] && strcmp(path, \"/\") && !git_project_top) {\n+\t\tchar *cp;\n+\t\tstruct stat st;\n+\t\tdir_length = strlen(path);\n+\t\tpath[dir_length] = '/';\n+\n+\t\tstrcpy(path + dir_length + 1, \".git\");\n+\t\tif (stat(path, &st) < 0) {\n+\t\t\tif (errno != ENOENT)\n+\t\t\t\treturn error(\"%s: %s\", path, strerror(errno));\n+\t\t\t/* notfound */\n+\t\t}\n+\t\telse if (S_ISDIR(st.st_mode)) {\n+\t\t\tpath[dir_length] = 0;\n+\t\t\tgit_project_top = strdup(path);\n+\t\t\tbreak;\n+\t\t}\n+\t\telse\n+\t\t\treturn error(\"%s: not a directory\", path);\n+\t\tpath[dir_length] = 0;\n+\t\tcp = strrchr(path, '/');\n+\t\tif (cp)\n+\t\t\t*cp = 0;\n+\t}\n+\tif (!git_project_top)\n+\t\treturn error(\"cannot find GIT_PROJECT_TOP\");\n+\n+\treturn 0;\n+}\n+\n+char *canon_path(const char *path)\n+{\n+\t/* path is either absolute path from root fs or\n+\t * relative to the git_cwd.  What is the relative path\n+\t * for that thing, viewed from GIT_PROJECT_TOP?\n+\t */\n+\tchar *cp, *op, *endp, *result = NULL;\n+\tchar *work = xmalloc(strlen(git_cwd) + strlen(path) + 2);\n+\tint pfxlen = strlen(git_project_top);\n+\n+\tif (path[0] == '/')\n+\t\tstrcpy(work, path);\n+\telse\n+\t\tsprintf(work, \"%s/%s\", git_cwd, path);\n+\t/* We will copy to *op starting from *cp while removing\n+\t * nonsense.  Initially op and cp are both set to one\n+\t * past the root-level '/'.\n+\t */\n+\top = cp = work + 1;\n+\tendp = cp + strlen(cp);\n+\twhile (cp < endp) {\n+\t\tchar *ep = strchr(cp, '/');\n+\t\tif (!ep)\n+\t\t\tep = endp; /* at terminating NUL */\n+\t\t/* Now look at what is between cp and ep. */\n+\t\tif (ep == cp) {\n+\t\t\t/* Remove double slashes.\n+\t\t\t * \"/xxx//foo\" ==> \"/xxx//foo\"\n+\t\t\t *    cp^              cp^\n+\t\t\t */\n+\t\t\tcp++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (*cp == '.') {\n+\t\t\t/* dot something.  What is it? */\n+\t\t\tif (cp[1] == 0 || cp[1] == '/') {\n+\t\t\t\t/* Remove trailing dot.\n+\t\t\t\t * \"/xxx/.\" ==> \"/xxx/.\"\n+\t\t\t\t *     cp^           cp^\n+\t\t\t\t * \"/xxx/./foo\" ==> \"/xxx/./foo\"\n+\t\t\t\t *     cp^               cp^\n+\t\t\t\t */\n+\t\t\t\tcp = ep;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (cp[1] == '.' && (cp[2] == 0 || cp[2] == '/')) {\n+\t\t\t\t/* Uplevel.\n+\t\t\t\t * \"/xxx/../foo\" ==> \"/xxx/../foo\"\n+\t\t\t\t *     cp^                  cp^\n+\t\t\t\t * while backspacing \"xxx\" in the op\n+\t\t\t\t */\n+\t\t\t\tcp = cp + 3;\n+\t\t\t\top -= 2;\n+\t\t\t\tif (op < work)\n+\t\t\t\t\top = work + 1;\n+\t\t\t\twhile (*op != '/' && work < op)\n+\t\t\t\t\top--;\n+\t\t\t\top++;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t}\n+\t\t/* otherwise there is no funnies */\n+\t\twhile (cp <= ep && *cp)\n+\t\t\t*op++ = *cp++;\n+\t}\n+\t*op = 0;\n+\tif (op[-1] == '/' && op != work)\n+\t\top[-1] = 0;\n+\n+\tif (!strncmp(git_project_top, work, pfxlen) &&\n+\t    (work[pfxlen] == '/' || work[pfxlen] == 0))\n+\t\tresult = strdup(work + pfxlen + 1);\n+\t/* otherwise, path is outside of git-project-top and we ignore it. */\n+\n+\tfree(work);\n+\treturn result;\n+}\n+\n+/****************************************************************/\n+\n+int setup_paths(void)\n+{\n+\tif (find_project_top())\n+\t\treturn -1;\n+\tif (initialize_ignore_list())\n+\t\treturn -1;\n+\treturn 0;\n+}\n+\n--- a/paths.h\n+++ b/paths.h\n@@ -0,0 +1,14 @@\n+/*\n+ * Copyright (c) 2005 Junio C Hamano\n+ */\n+#ifndef _PATHS_H_\n+#define _PATHS_H_\n+\n+int setup_paths(void);\n+extern char *git_project_top;\n+\n+char *canon_path(const char *);\n+int path_ignored(const char *);\n+int verify_path(const char *);\n+\n+#endif\n--- a/run-with-user-path.c\n+++ b/run-with-user-path.c\n@@ -0,0 +1,61 @@\n+/*\n+ * Copyright (c) 2005 Junio C Hamano\n+ */\n+#include <unistd.h>\n+#include \"cache.h\"\n+#include \"paths.h\"\n+\n+static int no_ignore = 0;\n+\n+static const char *usage_rwup = \n+\"git-run-with-user-path [ --no-ignore ] <command> <argument>... -- <path>...\";\n+\n+static int prepare_path_args(char **exec_param, char **path)\n+{\n+\tint i, cnt;\n+\tchar *canon;\n+\n+\tfor (i = cnt = 0; path[i]; i++) {\n+\t\tcanon = canon_path(path[i]);\n+\t\tif (no_ignore || !path_ignored(canon))\n+\t\t\texec_param[cnt++] = canon;\n+\t}\n+\treturn cnt;\n+}\n+\n+int main(int ac, char **av)\n+{\n+\tchar **exec_param;\n+\tint i, command_end, cnt_path;\n+\n+\tif (setup_paths())\n+\t\texit(1);\n+\n+\twhile (1 < ac && av[1][0] == '-') {\n+\t\tif (!strcmp(av[1], \"--no-ignore\"))\n+\t\t\tno_ignore = 1;\n+\t\telse\n+\t\t\tbreak;\n+\t\tac--; av++;\n+\t}\n+\tfor (i = 1; i < ac; i++)\n+\t\tif (!strcmp(av[i], \"--\"))\n+\t\t\tbreak;\n+\tif (ac <= i)\n+\t\tdie(usage_rwup); /* no -- to start path */\n+\n+\tcommand_end = i; /* pointing at -- */\n+\n+\t/* command command arg1 arg2 ... path1 path2 ... NULL */\n+\texec_param = xcalloc(ac, sizeof(char *));\n+\texec_param[ac - 1] = 0;\n+\tfor (i = 1; i < command_end; i++)\n+\t\texec_param[i - 1] = av[i];\n+\tcnt_path = prepare_path_args(exec_param + command_end - 1,\n+\t\t\t\t     av + command_end + 1);\n+\n+\tchdir(git_project_top);\n+\texecvp(exec_param[0], exec_param);\n+\n+\texit(0);\n+}\n--- a/t/README\n+++ b/t/README\n@@ -73,6 +73,7 @@\n \t4 - the diff commands\n \t5 - the pull and exporting commands\n \t6 - the revision tree commands (even e.g. merge-base)\n+\t7 - the non-core commands and helpers\n \n Second digit tells the particular command we are testing.\n \n--- a/t/t7000-git-run-with-user-path-basic.sh\n+++ b/t/t7000-git-run-with-user-path-basic.sh\n@@ -0,0 +1,66 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005, Junio C Hamano\n+#\n+\n+test_description='git-run-with-user-path basic test.\n+\n+The command is used to help running core GIT commands that always\n+expect to be run from the top level directory (i.e. the directory\n+that corresponds to the top of tree GIT_INDEX_FILE describes).\n+'\n+\n+. ./test-lib.sh\n+\n+LF='\n+'\n+HERE=$(pwd)\n+\n+test_expect_success \\\n+setup '\n+mkdir path0 path1 path1/path2\n+for p in path0/file0 path1/file1 path1/path2/file2\n+do\n+    echo hello >$p\n+    git-update-cache --add -- $p\n+done\n+'\n+\n+test_expect_success \\\n+'finding paths from a subdirectory' '\n+    case \"$(cd path0 &&\n+            git-run-with-user-path --no-ignore cat -- \\\n+\t    file0 ../path1/path2/file2)\" in\n+    \"hello${LF}hello\") : ;;\n+    *) (exit 1) ;;\n+    esac\n+'\n+\n+test_expect_success \\\n+'feeding find output via xargs from a subdirectory' '\n+    case \"$(cd path0 &&\n+\t    find . ../path1 -type f -print0 |\n+\t    xargs -r -0 git-run-with-user-path --no-ignore cat --)\" in\n+    \"hello${LF}hello${LF}hello\") : ;;\n+    *) (exit 1) ;;\n+    esac\n+'\n+\n+cd $HERE\n+mv .git .svn\n+GIT_DIR=$(pwd)/.svn\n+GIT_PROJECT_TOP=$(pwd)\n+export GIT_DIR GIT_PROJECT_TOP\n+\n+test_expect_success \\\n+'feeding find output via xargs from a subdirectory (with GIT_PROJECT_TOP)' '\n+    case \"$(cd path0 &&\n+            find . ../path1 -type f -print0 |\n+\t    xargs -r -0 git-run-with-user-path --no-ignore cat --)\" in\n+    \"hello${LF}hello${LF}hello\") : ;;\n+    *) (exit 1) ;;\n+    esac\n+    cd ..\n+'\n+\n+test_done\n--- a/update-cache.c\n+++ b/update-cache.c\n@@ -5,6 +5,7 @@\n  */\n #include <signal.h>\n #include \"cache.h\"\n+#include \"paths.h\"\n \n /*\n  * Default to not allowing changes to the list of files. The\n@@ -257,34 +258,6 @@\n \treturn has_errors;\n }\n \n-/*\n- * We fundamentally don't like some paths: we don't want\n- * dot or dot-dot anywhere, and in fact, we don't even want\n- * any other dot-files (.git or anything else). They\n- * are hidden, for chist sake.\n- *\n- * Also, we don't want double slashes or slashes at the\n- * end that can make pathnames ambiguous.\n- */\n-static int verify_path(char *path)\n-{\n-\tchar c;\n-\n-\tgoto inside;\n-\tfor (;;) {\n-\t\tif (!c)\n-\t\t\treturn 1;\n-\t\tif (c == '/') {\n-inside:\n-\t\t\tc = *path++;\n-\t\t\tif (c != '/' && c != '.' && c != '\\0')\n-\t\t\t\tcontinue;\n-\t\t\treturn 0;\n-\t\t}\n-\t\tc = *path++;\n-\t}\n-}\n-\n static int add_cacheinfo(char *arg1, char *arg2, char *arg3)\n {\n \tint size, len, option;\n------------------------------------------------\n\n"},{"id":"3457","messageId":"20050517190355.GA7136@pasky.ji.cz","threadId":"639","inReplyTo":"7voebbpuxs.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-17T19:03:55Z","receivedAt":"2005-05-17T19:03:55Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Mon, May 16, 2005 at 08:05:19AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> --- a/paths.c\n> +++ b/paths.c\n> @@ -0,0 +1,199 @@\n> +static int initialize_ignore_list(void)\n> +{\n> +\t/* Put the Porcelain layer ignore logic initialization here.\n> +\t * Return non-zero after issuing appropriate error message\n> +\t * if initialization fails.\n> +\t */\n> +\treturn 0;\n> +}\n> +\n> +int path_ignored(const char *path)\n> +{\n> +\tif (!verify_path(path))\n> +\t\treturn 1;\n> +\n> +\t/* Put the Porcelain layer ignore logic here.\n> +\t * Return non-zero if path is to be ignored.\n> +\t */\n> +\treturn 0;\n> +}\n\nI actually think you shouldn't. All the Porcelain layers should\nhopefully use the same git toolkit layer, not each one shipping own due\nto differences in things like this.\n\nIf we don't agree on something common (implemented in a way to be\nstill circumventable by a porcelain layer if desired), I wouldn't put\nthe ignore logic inside at all.\n\n> +/****************************************************************/\n> +\n> +/* Path canonicalization part */\n\nAnd why is this in the library?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3460","messageId":"7vk6lxfybc.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050517190355.GA7136@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-17T19:27:03Z","receivedAt":"2005-05-17T19:27:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\n>> +int path_ignored(const char *path)\n>> +{\n>> +\tif (!verify_path(path))\n>> +\t\treturn 1;\n>> +\n>> +\t/* Put the Porcelain layer ignore logic here.\n>> +\t * Return non-zero if path is to be ignored.\n>> +\t */\n>> +\treturn 0;\n>> +}\n\nPB> I actually think you shouldn't. All the Porcelain layers should\nPB> hopefully use the same git toolkit layer, not each one shipping own due\nPB> to differences in things like this.\n\nWhat you said above _is_ exactly my intention.  I phrased that\ncomment very badly.  It should have said:\n\n    /* We _will_ put the \"ignore logic Porcelain layers agree upon\"\n     * here, once we have a concensus.\n     *\n     * The code should return non-zero if path is to be ignored.\n     */\n\nI did not put any implementation there because I do not think we\nhave agreed upon anything yet.  This patch is to establish\nthe framework.  \n\nThe second patch is separate, because it is _my_ version of the\nignore logic proposal, to serve as a sample.  Whatever ignore\nlogic is agreed upon, that _will_ be in the place you pointed\nout and there will be no choice.  Everybody _will_ use the\nignore logic.\n\n>> +/****************************************************************/\n>> +\n>> +/* Path canonicalization part */\n\nPB> And why is this in the library?\n\nWhy not?  It is something other programs would eventually find\nuseful.\n\nAlso the second patch, a sample implementation of ignore logic I\nproposed, wants to know GIT_PROJECT_TOP to figure out the file\npointed at by GIT_DIR/.git/info/ignore-file.\n\nAlso it would not hurt if you are always running from the\nproject top and give only verify_path() approved paths.  Then\ncanon_path would become identity function.\n\ngit-run-with-user-path is useful both in implementing\nporcelain-add if the porcelain's policy is to take filesystem\npaths not GIT paths, like this:\n\n    #!/bin/sh\n    # porcelain-add\n    exec git-run-with-user-path git-update-cache --add -- -- \"$@\"\n\nAlso if the porcelain's policy is to take GIT paths not\nfilesystem paths, then users can say:\n\n    $ find . ! -type d -print0 |\n      xargs -0 git-run-with-user-path cg-add --\n\nYou cannot use both for obvious reasons.\n\n"},{"id":"3468","messageId":"20050517203500.GH7136@pasky.ji.cz","threadId":"639","inReplyTo":"7vk6lxfybc.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-17T20:35:00Z","receivedAt":"2005-05-17T20:35:00Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Tue, May 17, 2005 at 09:27:03PM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> >>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n> \n> >> +int path_ignored(const char *path)\n> >> +{\n> >> +\tif (!verify_path(path))\n> >> +\t\treturn 1;\n> >> +\n> >> +\t/* Put the Porcelain layer ignore logic here.\n> >> +\t * Return non-zero if path is to be ignored.\n> >> +\t */\n> >> +\treturn 0;\n> >> +}\n> \n> PB> I actually think you shouldn't. All the Porcelain layers should\n> PB> hopefully use the same git toolkit layer, not each one shipping own due\n> PB> to differences in things like this.\n> \n> What you said above _is_ exactly my intention.  I phrased that\n> comment very badly.  It should have said:\n> \n>     /* We _will_ put the \"ignore logic Porcelain layers agree upon\"\n>      * here, once we have a concensus.\n>      *\n>      * The code should return non-zero if path is to be ignored.\n>      */\n> \n> I did not put any implementation there because I do not think we\n> have agreed upon anything yet.  This patch is to establish\n> the framework.  \n\nOk, so this just bad comment. :-) No problem then.\n\n\nRegarding having the code in the library, well, I'm thinking about why\nnot to just put this logic into all the git commands. Unfortunately I\ncan't find the email with Linus' argumentation against that right now.\n:-(\n\n> git-run-with-user-path is useful both in implementing\n> porcelain-add if the porcelain's policy is to take filesystem\n> paths not GIT paths, like this:\n\nActually, my doubts about general usefulness of this wrapper are\ngrowing. Cogito is unlikely to ever make use of it since it has to\nfigure out the .git location anyway for own use (it keeps plenty of own\nfiles there). But that's likely what any other porcelain layer would\nhave to do as well, isn't it? The wrapper could still be useful for the\nstandalone users, though.\n\nAnother thing is, I don't think git-run-with-user-path is the right name.\nI think it doesn't make much sense on its own, and the wrapper is\nactually doing more anyway, applying the ignore rules. What about\ncalling it just git-run-wrapper?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3470","messageId":"7v4qd1tuud.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050517203500.GH7136@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junio@siamese.dyndns.org","sentAt":"2005-05-17T21:18:18Z","receivedAt":"2005-05-17T21:18:18Z","isPatch":true,"sender":{"key":"junio@siamese.dyndns.org","avatar":null},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> Actually, my doubts about general usefulness of this wrapper are\nPB> growing. Cogito is unlikely to ever make use of it since it has to\nPB> figure out the .git location anyway for own use (it keeps plenty of own\nPB> files there).\n\nI think \"having to figure out .git anyway\" is backwards, if your\nplan is to make Cogito take filesystem paths as opposed to GIT\npaths.  If the plan for Cogito is to take always GIT paths,\nwhich is a sensible way as well, then it is irrelevant for the\nimplementation of Cogito, but then it becomes useful for users\nof Cogito).\n\nIf your plan is to make Cogito take filesystem paths, then you\ncan move bulk of the code currently in cg-blah, except the part\nthat picks up non-path parameters, to cg-Xblah, and reduce\ncg-blah implementation down to just:\n\n    ... parse options by shifting \"$@\" out.\n    ... then\n    git-run-with-user-path cg-Xblah $non-path-opts -- \"$@\"\n\nand you can rip \"the code to figure out .git\" out from cg-Xblah.\nThere is nothing to figure out at that point; it always is\n${GIT_DIR-.git}/.\n\n"},{"id":"3476","messageId":"20050517213752.GO7136@pasky.ji.cz","threadId":"639","inReplyTo":"7v4qd1tuud.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-17T21:37:52Z","receivedAt":"2005-05-17T21:37:52Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Tue, May 17, 2005 at 11:18:18PM CEST, I got a letter\nwhere Junio C Hamano <junio@siamese.dyndns.org> told me that...\n> If your plan is to make Cogito take filesystem paths, then you\n\nYes, that's my plan.\n\n> can move bulk of the code currently in cg-blah, except the part\n> that picks up non-path parameters, to cg-Xblah, and reduce\n> cg-blah implementation down to just:\n> \n>     ... parse options by shifting \"$@\" out.\n>     ... then\n>     git-run-with-user-path cg-Xblah $non-path-opts -- \"$@\"\n> \n> and you can rip \"the code to figure out .git\" out from cg-Xblah.\n> There is nothing to figure out at that point; it always is\n> ${GIT_DIR-.git}/.\n\nBut that won't work good enough for me. E.g. when committing in a\nsubdirectory, I want to commit only changes made in the subdirectory,\netc.\n\nNot even talking about much uglier implementation (that could be\nremedied by calling myself recursively with some special argument).\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3480","messageId":"7vzmutqz5f.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050517213752.GO7136@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-17T22:13:32Z","receivedAt":"2005-05-17T22:13:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> But that won't work good enough for me. E.g. when committing in a\nPB> subdirectory, I want to commit only changes made in the subdirectory,\nPB> etc.\n\nAssuming that you have something that lets you commit selected\nfiles when you are at the top level (say cg-commit), and further\nassuming that today it only works from the toplevel, that is:\n\n    $ pwd\n    /usr/src/linux\n    $ cg-commit fs/ext?/Makefile\n\nworks today, what I am saying is:\n\n    $ pwd\n    /usr/src/linux/fs\n    $ git-run-with-user-path cg-commit -- ext?/Makefile\n\nwould work.\n\nUsually the command like cg-commit would take non-path\nparameters, so if this works today:\n\n    $ pwd\n    /usr/src/linux\n    $ cg-commit -m 'Changed Makefile' fs/ext?/Makefile\n\nthen:\n\n    $ pwd\n    /usr/src/linux/fs\n    $ git-run-with-user-path cg-commit -m 'Changed Makefile' -- ext?/Makefile\n\nwould work.\n\nOnce you have a core that works well but only at the top\ndirectory level, then you can make a thin wrapper using\ngit-run-with-user-path to make that work equally well with the\nfilesystem path from subdirectories.  And the core-ish thing\nthat only works at the top directory level does not need to\nworry about finding .git/ anymore, which is the whole point of\nwhat this helper is giving you.\n\n\n\nBTW, I am wondering if your choice of cg-commit as an example\n(as opposed to something else like diff or add) is a flamebait\nor just an innocent random example ;-)?\n\n"},{"id":"3517","messageId":"20050518213309.GD10358@pasky.ji.cz","threadId":"639","inReplyTo":"7vzmutqz5f.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-18T21:33:09Z","receivedAt":"2005-05-18T21:33:09Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Wed, May 18, 2005 at 12:13:32AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> >>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n> \n> PB> But that won't work good enough for me. E.g. when committing in a\n> PB> subdirectory, I want to commit only changes made in the subdirectory,\n> PB> etc.\n> \n> Assuming that you have something that lets you commit selected\n> files when you are at the top level (say cg-commit), and further\n> assuming that today it only works from the toplevel, that is:\n> \n>     $ pwd\n>     /usr/src/linux\n>     $ cg-commit fs/ext?/Makefile\n> \n> works today, what I am saying is:\n> \n>     $ pwd\n>     /usr/src/linux/fs\n>     $ git-run-with-user-path cg-commit -- ext?/Makefile\n> \n> would work.\n\nYes. But if you do just cg-commit in the subdirectory, it won't work.\nYou could pass the original directory in some environment variable or\nwhatever, but I think that's just not worth the trouble for Cogito -\nit's much easier for it when you just stay in the directory you are in\nand instead set the environment variables so that the git toolkit DTRT.\n(I like this acronym. :-)\n\n> BTW, I am wondering if your choice of cg-commit as an example\n> (as opposed to something else like diff or add) is a flamebait\n> or just an innocent random example ;-)?\n\nIt was completely innocent. :-) How would it be a flamebait?\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3522","messageId":"7vekc4nom5.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050518213309.GD10358@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-18T22:41:38Z","receivedAt":"2005-05-18T22:41:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\n>> $ pwd\n>> /usr/src/linux/fs\n>> $ git-run-with-user-path cg-commit -- ext?/Makefile\n>> \n>> would work.\n\nPB> Yes. But if you do just cg-commit in the subdirectory, it won't work.\n\nThe point of git-run-with-user-path is that it canonicalizes and\nfilters the paths, chdir(2)'s to GIT_PROJECT_TOP before running\ncg-commit.  So when cg-commit starts in the above example,\n\n    (1) its $cwd is /usr/src/linux and your .git subdirectory is\n        right there in ./.git/\n    (2) it gets fs/ext2/Makefile and fs/ext3/Makefile as arguments.\n\n>> BTW, I am wondering if your choice of cg-commit as an example\n>> (as opposed to something else like diff or add) is a flamebait\n>> or just an innocent random example ;-)?\n\nPB> It was completely innocent. :-) How would it be a flamebait?\n\n<http://members.cox.net/junkio/per-file-commit.txt> ;-).\n\n"},{"id":"3523","messageId":"20050518232408.GA18281@pasky.ji.cz","threadId":"639","inReplyTo":"7vekc4nom5.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-18T23:24:08Z","receivedAt":"2005-05-18T23:24:08Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, May 19, 2005 at 12:41:38AM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> >>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n> \n> >> $ pwd\n> >> /usr/src/linux/fs\n> >> $ git-run-with-user-path cg-commit -- ext?/Makefile\n> >> \n> >> would work.\n> \n> PB> Yes. But if you do just cg-commit in the subdirectory, it won't work.\n> \n> The point of git-run-with-user-path is that it canonicalizes and\n> filters the paths, chdir(2)'s to GIT_PROJECT_TOP before running\n> cg-commit.  So when cg-commit starts in the above example,\n> \n>     (1) its $cwd is /usr/src/linux and your .git subdirectory is\n>         right there in ./.git/\n>     (2) it gets fs/ext2/Makefile and fs/ext3/Makefile as arguments.\n\nYes. My point is that sometimes the Cogito commands have\ndirectory-specific functionality even when called without any arguments.\n\n$ pwd\n/usr/src/linux\n$ date >>README\n$ cd fs\n$ date >>Makefile\n$ cg-commit\n\nwill commit only the fs/Makefile change.\n\n> >> BTW, I am wondering if your choice of cg-commit as an example\n> >> (as opposed to something else like diff or add) is a flamebait\n> >> or just an innocent random example ;-)?\n> \n> PB> It was completely innocent. :-) How would it be a flamebait?\n> \n> <http://members.cox.net/junkio/per-file-commit.txt> ;-).\n\nJIT's snapshotting makes up for it, I think. It has some beauty. :-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3526","messageId":"7v64xgnl55.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050518232408.GA18281@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-18T23:56:38Z","receivedAt":"2005-05-18T23:56:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> Yes. My point is that sometimes the Cogito commands have\nPB> directory-specific functionality even when called without any arguments.\n\nPB> $ pwd\nPB> /usr/src/linux\nPB> $ date >>README\nPB> $ cd fs\nPB> $ date >>Makefile\nPB> $ cg-commit\n\nPB> will commit only the fs/Makefile change.\n\nAh, thanks.  That what I missed.\n\n\n\n"},{"id":"3527","messageId":"Pine.LNX.4.58.0505181731450.18337@ppc970.osdl.org","threadId":"639","inReplyTo":"7v64xgnl55.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-19T00:34:47Z","receivedAt":"2005-05-19T00:34:47Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Wed, 18 May 2005, Junio C Hamano wrote:\n> \n> PB> Yes. My point is that sometimes the Cogito commands have\n> PB> directory-specific functionality even when called without any arguments.\n> \n> PB> $ pwd\n> PB> /usr/src/linux\n> PB> $ date >>README\n> PB> $ cd fs\n> PB> $ date >>Makefile\n> PB> $ cg-commit\n> \n> PB> will commit only the fs/Makefile change.\n> \n> Ah, thanks.  That what I missed.\n\nNote that if git-run-with-user-path just has some way to tell what the\nrelative pathname of the original program was (say $DEF_SUBDIRECTORY),\nthis could still fairly easily be handled: having the cg-Xcommit program\nsay \"if there are no arguments, we default to $DEF_SUBDIRECTORY\" rather\nthan \"with no arguments, default to '.'\".\n\nI don't personally much care, since this is all porcelain, but basically I\ndon't think these things are in any way mutually incompatible, and I do\nbelieve that git-run-with-user-path _could_ be a good way to abstract out\nthe \"where the heck in the tree am I?\" issues.\n\n\t\tLinus\n"},{"id":"3536","messageId":"20050519074007.GI4738@cip.informatik.uni-erlangen.de","threadId":"639","inReplyTo":"20050518232408.GA18281@pasky.ji.cz","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Thomas Glanzmann","fromEmail":"sithglan@stud.uni-erlangen.de","sentAt":"2005-05-19T07:40:07Z","receivedAt":"2005-05-19T07:40:07Z","isPatch":true,"sender":{"key":"sithglan@stud.uni-erlangen.de","avatar":null},"body":"Hello,\n\n> > <http://members.cox.net/junkio/per-file-commit.txt> ;-).\n\n> I think the workflow that involves per-file commit is\n> fundamentally broken at two levels.\n\nI disagree here. We at FAUmachine often have FLAGS to turn on specific\nfeatures or debugging output by tweaking a headerfile. However we commit\noften and work in small steps (at the moment using CVS because every\ndeveloper has write access). And we definitely don't want to tweak the\nheader file every time we commit, so I often do a:\n\ncvs diff > diff\nvim diff\nlsdiff diff\ncvs commit <interesting files here>\n\n\tThomas\n"},{"id":"3539","messageId":"7voeb7lj48.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"20050519074007.GI4738@cip.informatik.uni-erlangen.de","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-19T08:23:19Z","receivedAt":"2005-05-19T08:23:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"TG\" == Thomas Glanzmann <sithglan@stud.uni-erlangen.de> writes:\n\nTG> Hello,\n>> > <http://members.cox.net/junkio/per-file-commit.txt> ;-).\n\n>> I think the workflow that involves per-file commit is\n>> fundamentally broken at two levels.\n\nTG> I disagree here. We at FAUmachine often have FLAGS to turn on specific\nTG> features or debugging output by tweaking a headerfile.\n\nSo what?  I would understand that in your workflow, the nature\nof that never-committed headerfile (the fact it only has\ndebugging tweaks and contains nothing substantially risky)\npractically minimizes the risk to the level everybody in the\ngroup feels acceptable.\n\nThat does not, however, change what I stated in the document:\nwhat you have in the repository is something that never existed\nin a work tree as a consistent whole and tested.\n\nYou are only saying is that it does not practically matter in\nyour workflow, only because what is floating (not checked in)\nare things you feel safe to drift.  I would not dare say that is\na wrong way to work.\n\nHowever, I feel fairly strong about this after being burned many\ntimes by careless coleagues who forgot to check in either newly\ncreated files or locally modified files and finding problems\nonly after customer installation happened.\n\n"},{"id":"3580","messageId":"7v7jhvymwe.fsf@assigned-by-dhcp.cox.net","threadId":"639","inReplyTo":"Pine.LNX.4.58.0505181731450.18337@ppc970.osdl.org","subject":"Re: [PATCH 1/2] Introduce git-run-with-user-path helper program.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-19T20:35:29Z","receivedAt":"2005-05-19T20:35:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> ... I do believe that git-run-with-user-path _could_ be a\nLT> good way to abstract out the \"where the heck in the tree am\nLT> I?\" issues.\n\nYes, I am still in search of a good way to abstract that issue\nout and I myself is not yet convinced that the command in its\ncurrent form _is_ a good enough way yet.\n\nWhat I am most unhappy about with it lies elsewhere, though.\nThere needs to be a better way to tell it how the underlying\ncommand handles non-paths arguments, so that I can just say\n\n    git-run-with-user-path <some option spec for the command> \\\n        command arg1 arg2 arg3 ...\n\nand if arg1 through argO is non-path options then have it\ncanonicalize and filter only starting from argO+1.  That would\nalleviate one issue I have with the current implementation.\n\n"}]}