refs.c: remove the update_ref_write function
[gitweb.git] / fast-import.c
index 4fd18a3574a6e72bb7a299b26b3f97fa20b8052d..e7f6e376d2233b141595f092a77a48f7cc4e71a6 100644 (file)
@@ -248,6 +248,7 @@ struct branch {
        uintmax_t last_commit;
        uintmax_t num_notes;
        unsigned active : 1;
+       unsigned delete : 1;
        unsigned pack_id : PACK_ID_BITS;
        unsigned char sha1[20];
 };
@@ -1485,14 +1486,11 @@ static int tree_content_set(
        unsigned int i, n;
        struct tree_entry *e;
 
-       slash1 = strchr(p, '/');
-       if (slash1)
-               n = slash1 - p;
-       else
-               n = strlen(p);
+       slash1 = strchrnul(p, '/');
+       n = slash1 - p;
        if (!n)
                die("Empty path component found in input");
-       if (!slash1 && !S_ISDIR(mode) && subtree)
+       if (!*slash1 && !S_ISDIR(mode) && subtree)
                die("Non-directories cannot have subtrees");
 
        if (!root->tree)
@@ -1501,7 +1499,7 @@ static int tree_content_set(
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
                if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
-                       if (!slash1) {
+                       if (!*slash1) {
                                if (!S_ISDIR(mode)
                                                && e->versions[1].mode == mode
                                                && !hashcmp(e->versions[1].sha1, sha1))
@@ -1552,7 +1550,7 @@ static int tree_content_set(
        e->versions[0].mode = 0;
        hashclr(e->versions[0].sha1);
        t->entries[t->entry_count++] = e;
-       if (slash1) {
+       if (*slash1) {
                e->tree = new_tree_content(8);
                e->versions[1].mode = S_IFDIR;
                tree_content_set(e, slash1 + 1, sha1, mode, subtree);
@@ -1576,11 +1574,8 @@ static int tree_content_remove(
        unsigned int i, n;
        struct tree_entry *e;
 
-       slash1 = strchr(p, '/');
-       if (slash1)
-               n = slash1 - p;
-       else
-               n = strlen(p);
+       slash1 = strchrnul(p, '/');
+       n = slash1 - p;
 
        if (!root->tree)
                load_tree(root);
@@ -1594,7 +1589,7 @@ static int tree_content_remove(
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
                if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
-                       if (slash1 && !S_ISDIR(e->versions[1].mode))
+                       if (*slash1 && !S_ISDIR(e->versions[1].mode))
                                /*
                                 * If p names a file in some subdirectory, and a
                                 * file or symlink matching the name of the
@@ -1602,7 +1597,7 @@ static int tree_content_remove(
                                 * exist and need not be deleted.
                                 */
                                return 1;
-                       if (!slash1 || !S_ISDIR(e->versions[1].mode))
+                       if (!*slash1 || !S_ISDIR(e->versions[1].mode))
                                goto del_entry;
                        if (!e->tree)
                                load_tree(e);
@@ -1644,11 +1639,8 @@ static int tree_content_get(
        unsigned int i, n;
        struct tree_entry *e;
 
-       slash1 = strchr(p, '/');
-       if (slash1)
-               n = slash1 - p;
-       else
-               n = strlen(p);
+       slash1 = strchrnul(p, '/');
+       n = slash1 - p;
        if (!n && !allow_root)
                die("Empty path component found in input");
 
@@ -1664,7 +1656,7 @@ static int tree_content_get(
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
                if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
-                       if (!slash1)
+                       if (!*slash1)
                                goto found_entry;
                        if (!S_ISDIR(e->versions[1].mode))
                                return 0;
@@ -1687,36 +1679,44 @@ static int tree_content_get(
 static int update_branch(struct branch *b)
 {
        static const char *msg = "fast-import";
-       struct ref_lock *lock;
+       struct ref_transaction *transaction;
        unsigned char old_sha1[20];
+       struct strbuf err = STRBUF_INIT;
 
-       if (is_null_sha1(b->sha1))
-               return 0;
        if (read_ref(b->name, old_sha1))
                hashclr(old_sha1);
-       lock = lock_any_ref_for_update(b->name, old_sha1, 0, NULL);
-       if (!lock)
-               return error("Unable to lock %s", b->name);
+       if (is_null_sha1(b->sha1)) {
+               if (b->delete)
+                       delete_ref(b->name, old_sha1, 0);
+               return 0;
+       }
        if (!force_update && !is_null_sha1(old_sha1)) {
                struct commit *old_cmit, *new_cmit;
 
                old_cmit = lookup_commit_reference_gently(old_sha1, 0);
                new_cmit = lookup_commit_reference_gently(b->sha1, 0);
-               if (!old_cmit || !new_cmit) {
-                       unlock_ref(lock);
+               if (!old_cmit || !new_cmit)
                        return error("Branch %s is missing commits.", b->name);
-               }
 
                if (!in_merge_bases(old_cmit, new_cmit)) {
-                       unlock_ref(lock);
                        warning("Not updating %s"
                                " (new tip %s does not contain %s)",
                                b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1));
                        return -1;
                }
        }
-       if (write_ref_sha1(lock, b->sha1, msg) < 0)
-               return error("Unable to update %s", b->name);
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, b->name, b->sha1, old_sha1,
+                                  0, 1, &err) ||
+           ref_transaction_commit(transaction, msg, &err)) {
+               ref_transaction_free(transaction);
+               error("%s", err.buf);
+               strbuf_release(&err);
+               return -1;
+       }
+       ref_transaction_free(transaction);
+       strbuf_release(&err);
        return 0;
 }
 
@@ -1735,15 +1735,32 @@ static void dump_tags(void)
 {
        static const char *msg = "fast-import";
        struct tag *t;
-       struct ref_lock *lock;
-       char ref_name[PATH_MAX];
+       struct strbuf ref_name = STRBUF_INIT;
+       struct strbuf err = STRBUF_INIT;
+       struct ref_transaction *transaction;
 
+       transaction = ref_transaction_begin(&err);
+       if (!transaction) {
+               failure |= error("%s", err.buf);
+               goto cleanup;
+       }
        for (t = first_tag; t; t = t->next_tag) {
-               sprintf(ref_name, "tags/%s", t->name);
-               lock = lock_ref_sha1(ref_name, NULL);
-               if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
-                       failure |= error("Unable to update %s", ref_name);
+               strbuf_reset(&ref_name);
+               strbuf_addf(&ref_name, "refs/tags/%s", t->name);
+
+               if (ref_transaction_update(transaction, ref_name.buf, t->sha1,
+                                          NULL, 0, 0, &err)) {
+                       failure |= error("%s", err.buf);
+                       goto cleanup;
+               }
        }
+       if (ref_transaction_commit(transaction, msg, &err))
+               failure |= error("%s", err.buf);
+
+ cleanup:
+       ref_transaction_free(transaction);
+       strbuf_release(&ref_name);
+       strbuf_release(&err);
 }
 
 static void dump_marks_helper(FILE *f,
@@ -2620,8 +2637,11 @@ static int parse_from(struct branch *b)
                        free(buf);
                } else
                        parse_from_existing(b);
-       } else if (!get_sha1(from, b->sha1))
+       } else if (!get_sha1(from, b->sha1)) {
                parse_from_existing(b);
+               if (is_null_sha1(b->sha1))
+                       b->delete = 1;
+       }
        else
                die("Invalid ref name or SHA1 expression: %s", from);