summaryrefslogtreecommitdiff
path: root/fast-import.c
diff options
context:
space:
mode:
Diffstat (limited to 'fast-import.c')
-rw-r--r--fast-import.c153
1 files changed, 119 insertions, 34 deletions
diff --git a/fast-import.c b/fast-import.c
index f246d5347b..dd3c99d60d 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1,4 +1,5 @@
/*
+(See Documentation/git-fast-import.txt for maintained documentation.)
Format of STDIN stream:
stream ::= cmd*;
@@ -18,11 +19,11 @@ Format of STDIN stream:
new_commit ::= 'commit' sp ref_str lf
mark?
- ('author' sp name '<' email '>' when lf)?
- 'committer' sp name '<' email '>' when lf
+ ('author' sp name sp '<' email '>' sp when lf)?
+ 'committer' sp name sp '<' email '>' sp when lf
commit_msg
- ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
- ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
+ ('from' sp committish lf)?
+ ('merge' sp committish lf)*
file_change*
lf?;
commit_msg ::= data;
@@ -40,15 +41,18 @@ Format of STDIN stream:
file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;
file_inm ::= 'M' sp mode sp 'inline' sp path_str lf
data;
+ note_obm ::= 'N' sp (hexsha1 | idnum) sp committish lf;
+ note_inm ::= 'N' sp 'inline' sp committish lf
+ data;
new_tag ::= 'tag' sp tag_str lf
- 'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
- ('tagger' sp name '<' email '>' when lf)?
+ 'from' sp committish lf
+ ('tagger' sp name sp '<' email '>' sp when lf)?
tag_msg;
tag_msg ::= data;
reset_branch ::= 'reset' sp ref_str lf
- ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
+ ('from' sp committish lf)?
lf?;
checkpoint ::= 'checkpoint' lf
@@ -75,7 +79,7 @@ Format of STDIN stream:
delim lf;
# note: declen indicates the length of binary_data in bytes.
- # declen does not include the lf preceeding the binary data.
+ # declen does not include the lf preceding the binary data.
#
exact_data ::= 'data' sp declen lf
binary_data;
@@ -87,6 +91,7 @@ Format of STDIN stream:
# stream formatting is: \, " and LF. Otherwise these values
# are UTF8.
#
+ committish ::= (ref_str | hexsha1 | sha1exp_str | idnum);
ref_str ::= ref;
sha1exp_str ::= sha1exp;
tag_str ::= tag;
@@ -132,8 +137,8 @@ Format of STDIN stream:
# always escapes the related input from comment processing.
#
# In case it is not clear, the '#' that starts the comment
- # must be the first character on that the line (an lf have
- # preceeded it).
+ # must be the first character on that line (an lf
+ # preceded it).
#
comment ::= '#' not_lf* lf;
not_lf ::= # Any byte that is not ASCII newline (LF);
@@ -150,6 +155,7 @@ Format of STDIN stream:
#include "refs.h"
#include "csum-file.h"
#include "quote.h"
+#include "exec_cmd.h"
#define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -210,7 +216,7 @@ struct tree_content;
struct tree_entry
{
struct tree_content *tree;
- struct atom_str* name;
+ struct atom_str *name;
struct tree_entry_ms
{
uint16_t mode;
@@ -311,7 +317,7 @@ static unsigned int object_entry_alloc = 5000;
static struct object_entry_pool *blocks;
static struct object_entry *object_table[1 << 16];
static struct mark_set *marks;
-static const char* mark_file;
+static const char *mark_file;
/* Our last blob */
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -670,7 +676,7 @@ static struct branch *lookup_branch(const char *name)
static struct branch *new_branch(const char *name)
{
unsigned int hc = hc_str(name, strlen(name)) % branch_table_sz;
- struct branch* b = lookup_branch(name);
+ struct branch *b = lookup_branch(name);
if (b)
die("Invalid attempt to create duplicate branch: %s", name);
@@ -867,7 +873,7 @@ static char *create_index(void)
/* Generate the fan-out array. */
c = idx;
for (i = 0; i < 256; i++) {
- struct object_entry **next = c;;
+ struct object_entry **next = c;
while (next < last) {
if ((*next)->sha1[0] != i)
break;
@@ -901,15 +907,12 @@ static char *keep_pack(char *curr_index_name)
static const char *keep_msg = "fast-import";
int keep_fd;
- chmod(pack_data->pack_name, 0444);
- chmod(curr_index_name, 0444);
-
keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
if (keep_fd < 0)
- die("cannot create keep file");
+ die_errno("cannot create keep file");
write_or_die(keep_fd, keep_msg, strlen(keep_msg));
if (close(keep_fd))
- die("failed to write keep file");
+ die_errno("failed to write keep file");
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
get_object_directory(), sha1_to_hex(pack_data->sha1));
@@ -932,7 +935,7 @@ static void unkeep_all_packs(void)
struct packed_git *p = all_packs[k];
snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
get_object_directory(), sha1_to_hex(p->sha1));
- unlink(name);
+ unlink_or_warn(name);
}
}
@@ -954,7 +957,7 @@ static void end_packfile(void)
close(pack_data->pack_fd);
idx_name = keep_pack(create_index());
- /* Register the packfile with core git's machinary. */
+ /* Register the packfile with core git's machinery. */
new_p = add_packed_git(idx_name, strlen(idx_name), 1);
if (!new_p)
die("core git rejected index %s", idx_name);
@@ -982,7 +985,7 @@ static void end_packfile(void)
}
else {
close(old_p->pack_fd);
- unlink(old_p->pack_name);
+ unlink_or_warn(old_p->pack_name);
}
free(old_p);
@@ -1036,7 +1039,7 @@ static int store_object(
git_SHA_CTX c;
z_stream s;
- hdrlen = sprintf((char*)hdr,"%s %lu", typename(type),
+ hdrlen = sprintf((char *)hdr,"%s %lu", typename(type),
(unsigned long)dat->len) + 1;
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, hdrlen);
@@ -1218,7 +1221,7 @@ static const char *get_mode(const char *str, uint16_t *modep)
static void load_tree(struct tree_entry *root)
{
- unsigned char* sha1 = root->versions[1].sha1;
+ unsigned char *sha1 = root->versions[1].sha1;
struct object_entry *myoe;
struct tree_content *t;
unsigned long size;
@@ -1259,8 +1262,8 @@ static void load_tree(struct tree_entry *root)
e->versions[0].mode = e->versions[1].mode;
e->name = to_atom(c, strlen(c));
c += e->name->str_len + 1;
- hashcpy(e->versions[0].sha1, (unsigned char*)c);
- hashcpy(e->versions[1].sha1, (unsigned char*)c);
+ hashcpy(e->versions[0].sha1, (unsigned char *)c);
+ hashcpy(e->versions[1].sha1, (unsigned char *)c);
c += 20;
}
free(buf);
@@ -1744,22 +1747,23 @@ static void parse_data(struct strbuf *sb)
static int validate_raw_date(const char *src, char *result, int maxlen)
{
const char *orig_src = src;
- char *endp, sign;
- unsigned long date;
+ char *endp;
+ unsigned long num;
errno = 0;
- date = strtoul(src, &endp, 10);
+ num = strtoul(src, &endp, 10);
+ /* NEEDSWORK: perhaps check for reasonable values? */
if (errno || endp == src || *endp != ' ')
return -1;
src = endp + 1;
if (*src != '-' && *src != '+')
return -1;
- sign = *src;
- date = strtoul(src + 1, &endp, 10);
- if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
+ num = strtoul(src + 1, &endp, 10);
+ if (errno || endp == src + 1 || *endp || (endp - orig_src) >= maxlen ||
+ 1400 < num)
return -1;
strcpy(result, orig_src);
@@ -2006,6 +2010,80 @@ static void file_change_cr(struct branch *b, int rename)
leaf.tree);
}
+static void note_change_n(struct branch *b)
+{
+ const char *p = command_buf.buf + 2;
+ static struct strbuf uq = STRBUF_INIT;
+ struct object_entry *oe = oe;
+ struct branch *s;
+ unsigned char sha1[20], commit_sha1[20];
+ uint16_t inline_data = 0;
+
+ /* <dataref> or 'inline' */
+ if (*p == ':') {
+ char *x;
+ oe = find_mark(strtoumax(p + 1, &x, 10));
+ hashcpy(sha1, oe->sha1);
+ p = x;
+ } else if (!prefixcmp(p, "inline")) {
+ inline_data = 1;
+ p += 6;
+ } else {
+ if (get_sha1_hex(p, sha1))
+ die("Invalid SHA1: %s", command_buf.buf);
+ oe = find_object(sha1);
+ p += 40;
+ }
+ if (*p++ != ' ')
+ die("Missing space after SHA1: %s", command_buf.buf);
+
+ /* <committish> */
+ s = lookup_branch(p);
+ if (s) {
+ hashcpy(commit_sha1, s->sha1);
+ } else if (*p == ':') {
+ uintmax_t commit_mark = strtoumax(p + 1, NULL, 10);
+ struct object_entry *commit_oe = find_mark(commit_mark);
+ if (commit_oe->type != OBJ_COMMIT)
+ die("Mark :%" PRIuMAX " not a commit", commit_mark);
+ hashcpy(commit_sha1, commit_oe->sha1);
+ } else if (!get_sha1(p, commit_sha1)) {
+ unsigned long size;
+ char *buf = read_object_with_reference(commit_sha1,
+ commit_type, &size, commit_sha1);
+ if (!buf || size < 46)
+ die("Not a valid commit: %s", p);
+ free(buf);
+ } else
+ die("Invalid ref name or SHA1 expression: %s", p);
+
+ if (inline_data) {
+ static struct strbuf buf = STRBUF_INIT;
+
+ if (p != uq.buf) {
+ strbuf_addstr(&uq, p);
+ p = uq.buf;
+ }
+ read_next_command();
+ parse_data(&buf);
+ store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
+ } else if (oe) {
+ if (oe->type != OBJ_BLOB)
+ die("Not a blob (actually a %s): %s",
+ typename(oe->type), command_buf.buf);
+ } else {
+ enum object_type type = sha1_object_info(sha1, NULL);
+ if (type < 0)
+ die("Blob not found: %s", command_buf.buf);
+ if (type != OBJ_BLOB)
+ die("Not a blob (actually a %s): %s",
+ typename(type), command_buf.buf);
+ }
+
+ tree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,
+ S_IFREG | 0644, NULL);
+}
+
static void file_change_deleteall(struct branch *b)
{
release_tree_content_recursive(b->branch_tree.tree);
@@ -2175,6 +2253,8 @@ static void parse_new_commit(void)
file_change_cr(b, 1);
else if (!prefixcmp(command_buf.buf, "C "))
file_change_cr(b, 0);
+ else if (!prefixcmp(command_buf.buf, "N "))
+ note_change_n(b);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
else {
@@ -2345,7 +2425,7 @@ static void import_marks(const char *input_file)
char line[512];
FILE *f = fopen(input_file, "r");
if (!f)
- die("cannot read %s: %s", input_file, strerror(errno));
+ die_errno("cannot read '%s'", input_file);
while (fgets(line, sizeof(line), f)) {
uintmax_t mark;
char *end;
@@ -2403,6 +2483,11 @@ int main(int argc, const char **argv)
{
unsigned int i, show_stats = 1;
+ git_extract_argv0_path(argv[0]);
+
+ if (argc == 2 && !strcmp(argv[1], "-h"))
+ usage(fast_import_usage);
+
setup_git_directory();
git_config(git_pack_config, NULL);
if (!pack_compression_seen && core_compression_seen)
@@ -2449,7 +2534,7 @@ int main(int argc, const char **argv)
fclose(pack_edges);
pack_edges = fopen(a + 20, "a");
if (!pack_edges)
- die("Cannot open %s: %s", a + 20, strerror(errno));
+ die_errno("Cannot open '%s'", a + 20);
} else if (!strcmp(a, "--force"))
force_update = 1;
else if (!strcmp(a, "--quiet"))