Implemented 'tag' command in fast-import.

Tags received from the frontend are generated in memory in a simple
linked list in the order that the tag commands were sent by the
frontend.  If multiple different tag objects for the same tag name
get generated the last one sent by the frontend will be the one
that gets written out at termination.  Multiple tag objects for
the same name will cause all older tags of the same name to be lost.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
Shawn O. Pearce 2006-08-24 03:12:13 -04:00
parent d6c7eb2c16
commit 72303d44e9

View File

@ -185,6 +185,13 @@ struct branch
unsigned char sha1[20];
};
struct tag
{
struct tag *next_tag;
const char *name;
unsigned char sha1[20];
};
/* Stats and misc. counters */
static unsigned long max_depth = 10;
@ -234,6 +241,10 @@ static unsigned long branch_table_sz = 1039;
static struct branch **branch_table;
static struct branch *active_branches;
/* Tag data */
static struct tag *first_tag;
static struct tag *last_tag;
/* Input stream parsing */
static struct strbuf command_buf;
static unsigned long next_mark;
@ -970,6 +981,21 @@ static void dump_branches()
}
}
static void dump_tags()
{
static const char *msg = "fast-import";
struct tag *t;
struct ref_lock *lock;
char path[PATH_MAX];
for (t = first_tag; t; t = t->next_tag) {
sprintf(path, "refs/tags/%s", t->name);
lock = lock_any_ref_for_update(path, NULL, 0);
if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
die("Can't write %s", path);
}
}
static void read_next_command()
{
read_line(&command_buf, stdin, '\n');
@ -1306,6 +1332,102 @@ static void cmd_new_branch()
die("An lf did not terminate the branch command as expected.");
}
static void cmd_new_tag()
{
char *str_uq;
const char *endp;
char *sp;
const char *from;
char *tagger;
struct branch *s;
void *msg;
size_t msglen;
char *body;
struct tag *t;
unsigned char sha1[20];
/* Obtain the new tag name from the rest of our command */
sp = strchr(command_buf.buf, ' ') + 1;
str_uq = unquote_c_style(sp, &endp);
if (str_uq) {
if (*endp)
die("Garbage after tag name in: %s", command_buf.buf);
sp = str_uq;
}
t = pool_alloc(sizeof(struct tag));
t->next_tag = NULL;
t->name = pool_strdup(sp);
if (last_tag)
last_tag->next_tag = t;
else
first_tag = t;
last_tag = t;
if (str_uq)
free(str_uq);
read_next_command();
/* from ... */
if (strncmp("from ", command_buf.buf, 5))
die("Expected from command, got %s", command_buf.buf);
from = strchr(command_buf.buf, ' ') + 1;
str_uq = unquote_c_style(from, &endp);
if (str_uq) {
if (*endp)
die("Garbage after string in: %s", command_buf.buf);
from = str_uq;
}
s = lookup_branch(from);
if (s) {
memcpy(sha1, s->sha1, 20);
} else if (*from == ':') {
unsigned long idnum = strtoul(from + 1, NULL, 10);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%lu not a commit", idnum);
memcpy(sha1, oe->sha1, 20);
} else if (!get_sha1(from, sha1)) {
unsigned long size;
char *buf;
buf = read_object_with_reference(sha1,
type_names[OBJ_COMMIT], &size, sha1);
if (!buf || size < 46)
die("Not a valid commit: %s", from);
free(buf);
} else
die("Invalid ref name or SHA1 expression: %s", from);
if (str_uq)
free(str_uq);
read_next_command();
/* tagger ... */
if (strncmp("tagger ", command_buf.buf, 7))
die("Expected tagger command, got %s", command_buf.buf);
tagger = strdup(command_buf.buf);
/* tag payload/message */
read_next_command();
msg = cmd_data(&msglen);
/* build the tag object */
body = xmalloc(67 + strlen(t->name) + strlen(tagger) + msglen);
sp = body;
sp += sprintf(sp, "object %s\n", sha1_to_hex(sha1));
sp += sprintf(sp, "type %s\n", type_names[OBJ_COMMIT]);
sp += sprintf(sp, "tag %s\n", t->name);
sp += sprintf(sp, "%s\n\n", tagger);
memcpy(sp, msg, msglen);
sp += msglen;
free(tagger);
free(msg);
store_object(OBJ_TAG, body, sp - body, NULL, t->sha1, 0);
free(body);
}
static const char fast_import_usage[] =
"git-fast-import [--objects=n] [--depth=n] [--active-branches=n] temp.pack";
@ -1367,6 +1489,8 @@ int main(int argc, const char **argv)
cmd_new_branch();
else if (!strncmp("commit ", command_buf.buf, 7))
cmd_new_commit();
else if (!strncmp("tag ", command_buf.buf, 4))
cmd_new_tag();
else
die("Unsupported command: %s", command_buf.buf);
}
@ -1375,6 +1499,7 @@ int main(int argc, const char **argv)
close(pack_fd);
write_index(idx_name);
dump_branches();
dump_tags();
fprintf(stderr, "%s statistics:\n", argv[0]);
fprintf(stderr, "---------------------------------------------------\n");