{"thread":{"id":"889","subject":"[PATCH 1/2] Changes to non-epoch.c code required for author-oriented git-rev-list changes","startedAt":"2005-06-10T09:23:34Z","lastAt":"2005-06-10T09:23:34Z","messageCount":1,"participants":["Jon Seymour"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"4819","messageId":"20050610092334.3913.qmail@blackcubes.dyndns.org","threadId":"889","inReplyTo":null,"subject":"[PATCH 1/2] Changes to non-epoch.c code required for author-oriented git-rev-list changes","fromName":"Jon Seymour","fromEmail":"jon.seymour@gmail.com","sentAt":"2005-06-10T09:23:34Z","receivedAt":"2005-06-10T09:23:34Z","isPatch":true,"sender":{"key":"jon.seymour@gmail.com","avatar":"https://avatars.githubusercontent.com/u/207131?v=4"},"body":"\nThis patch contains some changes to the remainder of git required by\nthe second patch of the set. The second patch adds author oriented \nfunctionality to git-rev-list.\n\nThis patch:\n    * factors out get_real_identity from commit-tree.c into user.c/h\n      so that it can later be re-used by rev-list.c\n\n    * introduces three new functions to commit.c\n       copy_commit_header\n\t    copies the value of a specified commit header into a buffer\n\n       copy_author\n\t    uses copy_commit_header to extract the author\n\n       copy_parents_in_header_order\n            makes an implicit coupling between epoch.c and commit.c\n            explicit so as to improve future maintainability of both\n\nSigned-off-by: Jon Seymour <jon.seymour@gmail.com>\n---\n\nI have split this patch into 2 because the epoch.c changes in the next\npatch of the set swamp the changes to parts of git that other people\ncare about and I wanted to make these changes easy to review.\n\nThe 2nd patch of this 2 patch set is:\n\n[PATCH 2/2] Add support for author-oriented git-rev-list switches [rev 11]\n\nDiverged from aa16021efcd969a44b480d0964e07d52167517db by Linus Torvalds <torvalds@ppc970.osdl.org>\n\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -42,9 +42,9 @@ install: $(PROG) $(SCRIPTS)\n \n LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n \t tag.o delta.o date.o index.o diff-delta.o patch-delta.o entry.o \\\n-\t epoch.o refs.o\n+\t epoch.o refs.o user.o\n LIB_FILE=libgit.a\n-LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h\n+LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h user.h\n \n LIB_H += strbuf.h\n LIB_OBJS += strbuf.o\n@@ -141,6 +141,7 @@ diffcore-pickaxe.o : $(LIB_H) diffcore.h\n diffcore-break.o : $(LIB_H) diffcore.h\n diffcore-order.o : $(LIB_H) diffcore.h\n epoch.o: $(LIB_H)\n+user.o: $(LIB_H)\n \n test: all\n \t$(MAKE) -C t/ all\ndiff --git a/commit-tree.c b/commit-tree.c\n--- a/commit-tree.c\n+++ b/commit-tree.c\n@@ -4,8 +4,8 @@\n  * Copyright (C) Linus Torvalds, 2005\n  */\n #include \"cache.h\"\n+#include \"user.h\"\n \n-#include <pwd.h>\n #include <time.h>\n #include <ctype.h>\n \n@@ -100,17 +100,16 @@ static char *commit_tree_usage = \"git-co\n \n int main(int argc, char **argv)\n {\n-\tint i, len;\n+\tint i;\n \tint parents = 0;\n \tunsigned char tree_sha1[20];\n \tunsigned char parent_sha1[MAXPARENT][20];\n \tunsigned char commit_sha1[20];\n \tchar *gecos, *realgecos, *commitgecos;\n-\tchar *email, *commitemail, realemail[1000];\n+\tchar *email, *commitemail, *realemail;\n \tchar date[50], realdate[50];\n \tchar *audate, *cmdate;\n \tchar comment[1000];\n-\tstruct passwd *pw;\n \tchar *buffer;\n \tunsigned int size;\n \n@@ -128,19 +127,7 @@ int main(int argc, char **argv)\n \t}\n \tif (!parents)\n \t\tfprintf(stderr, \"Committing initial tree %s\\n\", argv[1]);\n-\tpw = getpwuid(getuid());\n-\tif (!pw)\n-\t\tdie(\"You don't exist. Go away!\");\n-\trealgecos = pw->pw_gecos;\n-\tlen = strlen(pw->pw_name);\n-\tmemcpy(realemail, pw->pw_name, len);\n-\trealemail[len] = '@';\n-\tgethostname(realemail+len+1, sizeof(realemail)-len-1);\n-\tif (!strchr(realemail+len+1, '.')) {\n-\t\tstrcat(realemail, \".\");\n-\t\tgetdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);\n-\t}\n-\n+\tget_real_identity(&realemail, &realgecos);\n \tdatestamp(realdate, sizeof(realdate));\n \tstrcpy(date, realdate);\n \ndiff --git a/commit.c b/commit.c\n--- a/commit.c\n+++ b/commit.c\n@@ -76,6 +76,12 @@ int parse_commit_buffer(struct commit *i\n \t       !get_sha1_hex(bufptr + 7, parent)) {\n \t\tstruct commit *new_parent = lookup_commit(parent);\n \t\tif (new_parent) {\n+\t\t\t/** \n+                         * note to maintainers - \n+                         * please read and modify copy_parents_in_header_order\n+                         * if this behaviour ever changes from stacking\n+                         * to queueing behaviour.\n+\t\t\t */\n \t\t\tcommit_list_insert(new_parent, &item->parents);\n \t\t\tadd_ref(&item->object, &new_parent->object);\n \t\t}\n@@ -302,3 +308,69 @@ int count_parents(struct commit * commit\n         return count;\n }\n \n+int copy_commit_header(struct commit * commit, char * header, int index, char * buffer, int len)\n+{\n+\tchar * p = commit->buffer;\n+\n+\twhile (*p != '\\n') {\t\t\n+\t\tchar * q = header;\n+\t\tint matched;\n+\n+\t\tfor (matched = 1; *p != ' ' && *p != '\\n'; p++, q++) {\n+\t\t\tmatched = matched && (*q==*p);\n+\t\t}\n+\t\tif (matched && index) {\n+\t\t\t/*\n+\t\t\t * if we matched but we haven't seen the \n+\t\t\t * index'th element yet, just decrement \n+\t\t\t * the index then pretend we didn't match\n+\t\t\t */\n+\t\t\tindex--;\n+\t\t\tmatched = 0;\n+\t\t}\n+\t\tif (!matched) {\t\t\t\n+\t\t\t/* skip to start of next header line */\t\t\t\n+\t\t\tfor (;*p!='\\n';p++)\n+\t\t\t\t;\n+\t\t\tp++;\n+\t\t} else {\t\t\t\n+\t\t\tint count = 0; /* number of characters in value */\n+\t\t\tif (*p == ' ') {\t\t\t\t\n+\t\t\t\tp++;\n+\t\t\t\tcount = 0;\n+\t\t\t\twhile(*p != '\\n') {\n+\t\t\t\t\tif (len > 0)\n+\t\t\t\t\t\t*buffer++=*p;\t\t\t\t\n+\t\t\t\t\tp++;\n+\t\t\t\t\tcount++;\n+\t\t\t\t\tlen--;\n+\t\t\t\t}\t\t\t\t\t\n+\t\t\t} \n+\t\t\tif (len > 0)\n+\t\t\t\t*buffer = 0;\n+\t\t\treturn (len > 0) ? count+1 : -(count+1);\n+\t\t}\t\t\t\n+\t}\n+\treturn 0;\n+}\n+\n+int copy_author(struct commit * commit, char * buffer, int len)\n+{\n+\treturn copy_commit_header(commit, \"author\", 0, buffer, len);\n+}\n+\n+/*\n+ * Always produces a list of parents in the order they actually\n+ * appear in the commit header. The correct implementation \n+ * of this function depends on decisions made in parse_commit().\n+ */\n+struct commit_list * copy_parents_in_header_order(struct commit * commit)\n+{\n+\tstruct commit_list * parents = commit->parents;\n+        struct commit_list * result = NULL;\n+\n+\tfor (parents = commit->parents;parents;parents = parents->next) {\n+\t\tcommit_list_insert(parents->item, &result);\n+\t}\n+\treturn result;\n+}\ndiff --git a/commit.h b/commit.h\n--- a/commit.h\n+++ b/commit.h\n@@ -53,4 +53,35 @@ struct commit *pop_most_recent_commit(st\n struct commit *pop_commit(struct commit_list **stack);\n \n int count_parents(struct commit * commit);\n+\n+/*\n+ * Copies the value of the (index+1)'th commit header matching the name \n+ * specified into the buffer supplied and append a trailing NUL.\n+ *\n+ * Returns n<0 if the buffer was too short, where -n is the required length.\n+ * \n+ * Returns 0 if the header doesn't exist.\n+ * \n+ * Returns n>0 where n is the length of the copied zero-terminated value, \n+ * including the terminating zero.\n+ */\n+int copy_commit_header(struct commit * commit, char * header, int index, char * buffer, int len);\n+\n+/*\n+ * Copies the commit's author value into the buffer supplied. \n+ * Return values as per copy_commit_header.\n+ */\n+int copy_author(struct commit * commit, char * buffer, int len);\n+\n+/*\n+ * Make a copy of the parents in header order. This is the\n+ * reverse of the parse order. Callers who need guarantees\n+ * about parents being in header order should use this \n+ * call whose semantics will never change even if the\n+ * implementation of parse_commit does.\n+ *\n+ * Callers are expected to destroy the copied list when\n+ * they are finished with it.\n+ */\n+struct commit_list * copy_parents_in_header_order(struct commit * commit);\n #endif /* COMMIT_H */\ndiff --git a/user.c b/user.c\nnew file mode 100644\n--- /dev/null\n+++ b/user.c\n@@ -0,0 +1,29 @@\n+#include \"cache.h\"\n+#include \"user.h\"\n+#include <string.h>\n+#include <pwd.h>\n+\n+void get_real_identity(char **email, char **gecos)\n+{\n+\tstatic char buffer[1000];\n+\tstruct passwd *pw;\n+\tint len;\n+\n+\tpw = getpwuid(getuid());\n+\tif (!pw)\n+\t\tdie(\"You don't exist. Go away!\");\n+\n+\tlen = strlen(pw->pw_name);\n+\tmemcpy(buffer, pw->pw_name, len);\n+\tbuffer[len] = '@';\n+\tgethostname(buffer + len + 1, sizeof(buffer) - len - 1);\n+\tif (!strchr(buffer + len + 1, '.')) {\n+\t\tstrcat(buffer, \".\");\n+\t\tgetdomainname(buffer + strlen(buffer), \n+\t\t\t\tsizeof(buffer) - strlen(buffer) - 1);\n+\t}\n+\tif (gecos)\n+\t\t*gecos = strdup(pw->pw_gecos);\n+\tif (email)\n+\t\t*email = strdup(buffer);\n+}\ndiff --git a/user.h b/user.h\nnew file mode 100644\n--- /dev/null\n+++ b/user.h\n@@ -0,0 +1,8 @@\n+#ifndef USER_H\n+#define USER_H\n+/*\n+ * Allocates two new strings to contain the real email and\n+ * name of the current user.\n+ */\n+extern void get_real_identity(char **email, char **gecos);\n+#endif\n"}]}