git-commit-vandalism/commit-tree.c
Junio C Hamano d19938ab60 Rename environment variables.
H. Peter Anvin mentioned that using SHA1_whatever as an
environment variable name is not nice and we should instead use
names starting with "GIT_" prefix to avoid conflicts.  Here is
what this patch does:

 * Renames the following environment variables:

    New name                           Old Name

    GIT_AUTHOR_DATE                    AUTHOR_DATE
    GIT_AUTHOR_EMAIL                   AUTHOR_EMAIL
    GIT_AUTHOR_NAME                    AUTHOR_NAME
    GIT_COMMITTER_EMAIL                COMMIT_AUTHOR_EMAIL
    GIT_COMMITTER_NAME                 COMMIT_AUTHOR_NAME
    GIT_ALTERNATE_OBJECT_DIRECTORIES   SHA1_FILE_DIRECTORIES
    GIT_OBJECT_DIRECTORY               SHA1_FILE_DIRECTORY

 * Introduces a compatibility macro, gitenv(), which does an
   getenv() and if it fails calls gitenv_bc(), which in turn
   picks up the value from old name while giving a warning about
   using an old name.

 * Changes all users of the environment variable to fetch
   environment variable with the new name using gitenv().

 * Updates the documentation and scripts shipped with Linus GIT
   distribution.

The transition plan is as follows:

 * We will keep the backward compatibility list used by gitenv()
   for now, so the current scripts and user environments
   continue to work as before.  The users will get warnings when
   they have old name but not new name in their environment to
   the stderr.

 * The Porcelain layers should start using new names.  However,
   just in case it ends up calling old Plumbing layer
   implementation, they should also export old names, taking
   values from the corresponding new names, during the
   transition period.

 * After a transition period, we would drop the compatibility
   support and drop gitenv().  Revert the callers to directly
   call getenv() but keep using the new names.

   The last part is probably optional and the transition
   duration needs to be set to a reasonable value.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-05-09 17:57:56 -07:00

183 lines
4.4 KiB
C

/*
* GIT - The information manager from hell
*
* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
#include <pwd.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define BLOCKING (1ul << 14)
/*
* FIXME! Share the code with "write-tree.c"
*/
static void init_buffer(char **bufp, unsigned int *sizep)
{
char *buf = xmalloc(BLOCKING);
*sizep = 0;
*bufp = buf;
}
static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...)
{
char one_line[2048];
va_list args;
int len;
unsigned long alloc, size, newsize;
char *buf;
va_start(args, fmt);
len = vsnprintf(one_line, sizeof(one_line), fmt, args);
va_end(args);
size = *sizep;
newsize = size + len;
alloc = (size + 32767) & ~32767;
buf = *bufp;
if (newsize > alloc) {
alloc = (newsize + 32767) & ~32767;
buf = xrealloc(buf, alloc);
*bufp = buf;
}
*sizep = newsize;
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;
char type[20];
unsigned long size;
buf = read_sha1_file(sha1, type, &size);
if (!buf || strcmp(type, expect))
die("%s is not a valid '%s' object", sha1_to_hex(sha1), expect);
free(buf);
}
/*
* Having more than two parents is not strange at all, and this is
* how multi-way merges are represented.
*/
#define MAXPARENT (16)
static char *commit_tree_usage = "commit-tree <sha1> [-p <sha1>]* < changelog";
int main(int argc, char **argv)
{
int i, len;
int parents = 0;
unsigned char tree_sha1[20];
unsigned char parent_sha1[MAXPARENT][20];
unsigned char commit_sha1[20];
char *gecos, *realgecos, *commitgecos;
char *email, *commitemail, realemail[1000];
char date[20], realdate[20];
char *audate;
char comment[1000];
struct passwd *pw;
char *buffer;
unsigned int size;
if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
usage(commit_tree_usage);
check_valid(tree_sha1, "tree");
for (i = 2; i < argc; i += 2) {
char *a, *b;
a = argv[i]; b = argv[i+1];
if (!b || strcmp(a, "-p") || get_sha1(b, parent_sha1[parents]))
usage(commit_tree_usage);
check_valid(parent_sha1[parents], "commit");
parents++;
}
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);
}
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));
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));
/*
* NOTE! This ordering means that the same exact tree merged with a
* different order of parents will be a _different_ changeset even
* if everything else stays the same.
*/
for (i = 0; i < parents; i++)
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);
/* And add the comment */
while (fgets(comment, sizeof(comment), stdin) != NULL)
add_buffer(&buffer, &size, "%s", comment);
write_sha1_file(buffer, size, "commit", commit_sha1);
printf("%s\n", sha1_to_hex(commit_sha1));
return 0;
}