From: ebiederm@xmission.com (Eric W. Biederman)
To: Linus Torvalds <torvalds@osdl.org>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: [PATCH] tagger id
Date: Mon, 11 Jul 2005 22:39:25 -0600 [thread overview]
Message-ID: <m1slyk63k2.fsf_-_@ebiederm.dsl.xmission.com> (raw)
In-Reply-To: <Pine.LNX.4.58.0507111815180.17536@g5.osdl.org> (Linus Torvalds's message of "Mon, 11 Jul 2005 18:15:52 -0700 (PDT)")
This patch adds a command git-id for use on
the command line to see what git will set your id too,
and for use in scripts (git-tag-script) so they can get your git id.
The common code for computing the git-id is moved to ident.c
Fix parse_date to not mind being passed a constant date
to parse.
The code to compute the identifier has been restructured
to at least make a reasonable stab at error handling. The
original version had so many unchecked return values it was
just scary to think about.
Eric
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ PROG= git-update-cache git-diff-files
git-diff-stages git-rev-parse git-patch-id git-pack-objects \
git-unpack-objects git-verify-pack git-receive-pack git-send-pack \
git-prune-packed git-fetch-pack git-upload-pack git-clone-pack \
- git-show-index
+ git-show-index git-id
all: $(PROG)
@@ -57,7 +57,7 @@ install: $(PROG) $(SCRIPTS)
LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \
tag.o date.o index.o diff-delta.o patch-delta.o entry.o path.o \
- epoch.o refs.o csum-file.o pack-check.o pkt-line.o connect.o
+ epoch.o refs.o csum-file.o pack-check.o pkt-line.o connect.o ident.o
LIB_FILE=libgit.a
LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h \
pack.h pkt-line.h refs.h
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -208,9 +208,14 @@ extern void *read_object_with_reference(
unsigned char *sha1_ret);
const char *show_date(unsigned long time, int timezone);
-void parse_date(char *date, char *buf, int bufsize);
+void parse_date(const char *date, char *buf, int bufsize);
void datestamp(char *buf, int bufsize);
+int git_ident(char *buf, size_t bufsize,
+ const char *env_name, const char *env_email, const char *env_date);
+int git_committer_ident(char *buf, size_t bufsize);
+int git_author_ident(char *buf, size_t bufsize);
+
static inline void *xmalloc(size_t size)
{
void *ret = malloc(size);
diff --git a/commit-tree.c b/commit-tree.c
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -5,9 +5,10 @@
*/
#include "cache.h"
-#include <pwd.h>
#include <time.h>
#include <ctype.h>
+#include <string.h>
+#include <errno.h>
#define BLOCKING (1ul << 14)
@@ -45,39 +46,6 @@ static void add_buffer(char **bufp, unsi
memcpy(buf + size, one_line, len);
}
-static void remove_special(char *p)
-{
- char c;
- char *dst = p, *src = p;
-
- for (;;) {
- c = *src;
- src++;
- switch(c) {
- case '\n': case '<': case '>':
- continue;
- }
- *dst++ = c;
- if (!c)
- break;
- }
-
- /*
- * Go back, and remove crud from the end: some people
- * have commas etc in their gecos field
- */
- dst--;
- while (--dst >= p) {
- unsigned char c = *dst;
- switch (c) {
- case ',': case ';': case '.':
- *dst = 0;
- continue;
- }
- break;
- }
-}
-
static void check_valid(unsigned char *sha1, const char *expect)
{
void *buf;
@@ -114,16 +82,13 @@ static int new_parent(int idx)
int main(int argc, char **argv)
{
- int i, len;
+ int i;
int parents = 0;
unsigned char tree_sha1[20];
unsigned char commit_sha1[20];
- char *gecos, *realgecos, *commitgecos;
- char *email, *commitemail, realemail[1000];
- char date[50], realdate[50];
- char *audate, *cmdate;
+ char committer[1000];
+ char author[1000];
char comment[1000];
- struct passwd *pw;
char *buffer;
unsigned int size;
@@ -142,35 +107,12 @@ int main(int argc, char **argv)
}
if (!parents)
fprintf(stderr, "Committing initial tree %s\n", argv[1]);
- pw = getpwuid(getuid());
- if (!pw)
- die("You don't exist. Go away!");
- realgecos = pw->pw_gecos;
- len = strlen(pw->pw_name);
- memcpy(realemail, pw->pw_name, len);
- realemail[len] = '@';
- gethostname(realemail+len+1, sizeof(realemail)-len-1);
- if (!strchr(realemail+len+1, '.')) {
- strcat(realemail, ".");
- getdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);
+ if (git_author_ident(author, sizeof(author)) < 0) {
+ die("Bad author! %s", strerror(errno));
+ }
+ if (git_committer_ident(committer, sizeof(committer)) < 0) {
+ die("Bad Committer! %s", strerror(errno));
}
-
- datestamp(realdate, sizeof(realdate));
- strcpy(date, realdate);
-
- commitgecos = gitenv("GIT_COMMITTER_NAME") ? : realgecos;
- commitemail = gitenv("GIT_COMMITTER_EMAIL") ? : realemail;
- gecos = gitenv("GIT_AUTHOR_NAME") ? : realgecos;
- email = gitenv("GIT_AUTHOR_EMAIL") ? : realemail;
- audate = gitenv("GIT_AUTHOR_DATE");
- if (audate)
- parse_date(audate, date, sizeof(date));
- cmdate = gitenv("GIT_COMMITTER_DATE");
- if (cmdate)
- parse_date(cmdate, realdate, sizeof(realdate));
-
- remove_special(gecos); remove_special(realgecos); remove_special(commitgecos);
- remove_special(email); remove_special(realemail); remove_special(commitemail);
init_buffer(&buffer, &size);
add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1));
@@ -184,8 +126,8 @@ int main(int argc, char **argv)
add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i]));
/* Person/date information */
- add_buffer(&buffer, &size, "author %s <%s> %s\n", gecos, email, date);
- add_buffer(&buffer, &size, "committer %s <%s> %s\n\n", commitgecos, commitemail, realdate);
+ add_buffer(&buffer, &size, "author %s <%s> %s\n", author);
+ add_buffer(&buffer, &size, "committer %s <%s> %s\n\n", committer);
/* And add the comment */
while (fgets(comment, sizeof(comment), stdin) != NULL)
diff --git a/date.c b/date.c
--- a/date.c
+++ b/date.c
@@ -224,7 +224,7 @@ static int is_date(int year, int month,
return 0;
}
-static int match_multi_number(unsigned long num, char c, char *date, char *end, struct tm *tm)
+static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm)
{
long num2, num3;
@@ -270,7 +270,7 @@ static int match_multi_number(unsigned l
/*
* We've seen a digit. Time? Year? Date?
*/
-static int match_digit(char *date, struct tm *tm, int *offset, int *tm_gmt)
+static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt)
{
int n;
char *end;
@@ -361,7 +361,7 @@ static int match_digit(char *date, struc
return n;
}
-static int match_tz(char *date, int *offp)
+static int match_tz(const char *date, int *offp)
{
char *end;
int offset = strtoul(date+1, &end, 10);
@@ -388,7 +388,7 @@ static int match_tz(char *date, int *off
/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
(i.e. English) day/month names, and it doesn't work correctly with %z. */
-void parse_date(char *date, char *result, int maxlen)
+void parse_date(const char *date, char *result, int maxlen)
{
struct tm tm;
int offset, sign, tm_gmt;
diff --git a/git-tag-script b/git-tag-script
--- a/git-tag-script
+++ b/git-tag-script
@@ -7,6 +7,7 @@ name="$1"
object=${2:-$(cat "$GIT_DIR"/HEAD)}
type=$(git-cat-file -t $object) || exit 1
+tagger=$(git-id) || exit 1
( echo "#"
echo "# Write a tag message"
@@ -17,8 +18,9 @@ grep -v '^#' < .editmsg | git-stripspace
[ -s .tagmsg ] || exit
-( echo -e "object $object\ntype $type\ntag $name\n"; cat .tagmsg ) > .tmp-tag
+( echo -e "object $object\ntype $type\ntag $name\ntagger $tagger\n"; cat .tagmsg ) > .tmp-tag
rm -f .tmp-tag.asc .tagmsg
gpg -bsa .tmp-tag && cat .tmp-tag.asc >> .tmp-tag
+mkdir -p "$GIT_DIR/refs/tags"
git-mktag < .tmp-tag > "$GIT_DIR/refs/tags/$name"
#rm .tmp-tag .tmp-tag.sig
diff --git a/id.c b/id.c
new file mode 100644
--- /dev/null
+++ b/id.c
@@ -0,0 +1,36 @@
+#include "cache.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+static char *id_usage = "git-id [--author | --committer]";
+
+int main(int argc, char **argv)
+{
+ char buf[1000];
+ int (*ident)(char *buf, size_t bufsize);
+ int i;
+
+ ident = git_committer_ident;
+ for(i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (strcmp(arg, "--author") == 0) {
+ ident = git_author_ident;
+ }
+ else if (strcmp(arg, "--committer") == 0) {
+ ident = git_committer_ident;
+ }
+ else {
+ usage(id_usage);
+ }
+ }
+
+
+ if (ident(buf, sizeof(buf)) < 0) {
+ die("Cannot resolve ident: %s\n", strerror(errno));
+ }
+
+ printf("%s\n", buf);
+
+ return 0;
+}
diff --git a/ident.c b/ident.c
new file mode 100644
--- /dev/null
+++ b/ident.c
@@ -0,0 +1,144 @@
+/*
+ * GIT - The information manager from hell
+ *
+ * Copyright (C) Eric Biederman, 2005
+ */
+#include "cache.h"
+
+#include <pwd.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#define MAX_NAME 1000
+#define MAX_EMAIL 1000
+#define MAX_DATE 50
+static void remove_special(char *p)
+{
+ char c;
+ char *dst = p, *src = p;
+
+ for (;;) {
+ c = *src;
+ src++;
+ switch(c) {
+ case '\n': case '<': case '>':
+ continue;
+ }
+ *dst++ = c;
+ if (!c)
+ break;
+ }
+
+ /*
+ * Go back, and remove crud from the end: some people
+ * have commas etc in their gecos field
+ */
+ dst--;
+ while (--dst >= p) {
+ unsigned char c = *dst;
+ switch (c) {
+ case ',': case ';': case '.':
+ *dst = 0;
+ continue;
+ }
+ break;
+ }
+}
+
+int git_ident(char *buf, size_t bufsize,
+ const char *env_name, const char *env_email, const char *env_date)
+{
+ int len;
+ char name[MAX_NAME];
+ char email[MAX_EMAIL];
+ char date[MAX_DATE];
+ struct passwd *pw;
+ int count;
+
+ /* Lookup the user in the password file */
+ pw = getpwuid(getuid());
+ if (!pw)
+ return -1;
+
+ /* Get the users full name */
+ strncpy(name, pw->pw_gecos, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+
+ /* Get the email address with error handling */
+ len = strlen(pw->pw_name);
+ if (len >= (sizeof(email) - 2)) {
+ /* Bad user name length */
+ errno = ENOMEM;
+ return -1;
+ }
+ memcpy(email, pw->pw_name, len);
+ email[len] = '@';
+ email[len + 1] = '\0';
+
+ if (gethostname(email+len+1, sizeof(email)-len-1) < 0) {
+ return -1;
+ }
+ email[sizeof(email) - 1] = '\0';
+ len = strlen(email);
+ if (!strchr(email+len+1, '.')) {
+ if (len >= (sizeof(email) - 1)) {
+ errno = ENOMEM;
+ return -1;
+ }
+ email[len] = '.';
+ if (getdomainname(email+len+1, sizeof(email) - len - 1) < 0) {
+ return -1;
+ }
+ }
+ /* Get the date */
+ datestamp(date, sizeof(date));
+
+ if (env_name) {
+ strncpy(name, env_name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ }
+ if (env_email) {
+ strncpy(email, env_email, sizeof(email));
+ email[sizeof(email) - 1] = '\0';
+ }
+ if (env_date) {
+ parse_date(env_date, date, sizeof(date));
+ }
+ remove_special(name);
+ remove_special(email);
+ count = snprintf(buf, bufsize, "%s <%s> %s", name, email, date);
+ if (count > bufsize) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (count < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int git_committer_ident(char *buf, size_t bufsize)
+{
+ const char *name;
+ const char *email;
+ const char *date;
+ name = gitenv("GIT_COMMITTER_NAME");
+ email = gitenv("GIT_COMMITTER_EMAIL");
+ date = gitenv("GIT_COMMITTER_DATE");
+ return git_ident(buf, bufsize, name, email, date);
+}
+
+int git_author_ident(char *buf, size_t bufsize)
+{
+ const char *name;
+ const char *email;
+ const char *date;
+ name = gitenv("GIT_AUTHOR_NAME");
+ email = gitenv("GIT_AUTHOR_EMAIL");
+ date = gitenv("GIT_AUTHOR_DATE");
+ return git_ident(buf, bufsize, name, email, date);
+}
+
diff --git a/mktag.c b/mktag.c
--- a/mktag.c
+++ b/mktag.c
@@ -42,7 +42,7 @@ static int verify_tag(char *buffer, unsi
int typelen;
char type[20];
unsigned char sha1[20];
- const char *object, *type_line, *tag_line;
+ const char *object, *type_line, *tag_line, *tagger_line;
if (size < 64 || size > MAXSIZE-1)
return -1;
@@ -92,6 +92,12 @@ static int verify_tag(char *buffer, unsi
return -1;
}
+ /* Verify the tagger line */
+ tagger_line = tag_line;
+
+ if (memcmp(tagger_line, "tagger", 6) || (tagger_line[6] == '\n'))
+ return -1;
+
/* The actual stuff afterwards we don't care about.. */
return 0;
}
@@ -119,7 +125,7 @@ int main(int argc, char **argv)
size += ret;
}
- // Verify it for some basic sanity: it needs to start with "object <sha1>\ntype "
+ // Verify it for some basic sanity: it needs to start with "object <sha1>\ntype\ntagger "
if (verify_tag(buffer, size) < 0)
die("invalid tag signature file");
next prev parent reply other threads:[~2005-07-12 4:43 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-07-11 1:18 Trial git RPM's Linus Torvalds
2005-07-11 15:24 ` Eric W. Biederman
2005-07-11 17:06 ` Linus Torvalds
2005-07-11 20:11 ` Horst von Brand
2005-07-11 21:03 ` Chris Wright
2005-07-12 15:59 ` Eric W. Biederman
2005-07-12 17:01 ` Linus Torvalds
2005-07-12 17:14 ` Eric W. Biederman
2005-07-12 17:27 ` Linus Torvalds
2005-07-12 17:46 ` Chris Wright
2005-07-12 0:55 ` Eric W. Biederman
2005-07-12 1:15 ` Linus Torvalds
2005-07-12 2:39 ` Eric W. Biederman
2005-07-12 4:39 ` Eric W. Biederman [this message]
2005-07-12 6:50 ` [PATCH] tagger id Eric W. Biederman
2005-07-12 8:44 ` Junio C Hamano
2005-07-12 15:04 ` Eric W. Biederman
2005-07-12 15:14 ` Petr Baudis
2005-07-12 21:16 ` Junio C Hamano
2005-07-15 0:46 ` Eric W. Biederman
2005-07-12 18:54 ` Linus Torvalds
2005-07-12 22:15 ` Eric W. Biederman
2005-07-12 23:42 ` Junio C Hamano
2005-07-15 0:36 ` Eric W. Biederman
2005-07-12 0:58 ` Trial git RPM's Eric W. Biederman
2005-07-11 20:34 ` Chris Wright
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m1slyk63k2.fsf_-_@ebiederm.dsl.xmission.com \
--to=ebiederm@xmission.com \
--cc=git@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).