compat: Add simplified merge sort implementation from glibc
[gitweb.git] / bundle.c
index 0869fcf0261de7217cc0b1dadd30a5259468d4f8..5c95eca07d19a6d3ed4e9000b5bb47eef90ff66e 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -6,6 +6,7 @@
 #include "revision.h"
 #include "list-objects.h"
 #include "run-command.h"
+#include "refs.h"
 
 static const char bundle_signature[] = "# v2 git bundle\n";
 
@@ -23,7 +24,8 @@ static void add_to_ref_list(const unsigned char *sha1, const char *name,
 }
 
 /* returns an fd */
-int read_bundle_header(const char *path, struct bundle_header *header) {
+int read_bundle_header(const char *path, struct bundle_header *header)
+{
        char buffer[1024];
        int fd;
        long fpos;
@@ -46,7 +48,7 @@ int read_bundle_header(const char *path, struct bundle_header *header) {
                        : &header->references;
                char delim;
 
-               if (buffer[len - 1] == '\n')
+               if (len && buffer[len - 1] == '\n')
                        buffer[len - 1] = '\0';
                if (get_sha1_hex(buffer + offset, sha1)) {
                        warning("unrecognized header: %s", buffer);
@@ -231,11 +233,17 @@ int create_bundle(struct bundle_header *header, const char *path,
                struct object_array_entry *e = revs.pending.objects + i;
                unsigned char sha1[20];
                char *ref;
+               const char *display_ref;
+               int flag;
 
                if (e->item->flags & UNINTERESTING)
                        continue;
                if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
                        continue;
+               if (!resolve_ref(e->name, sha1, 1, &flag))
+                       flag = 0;
+               display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
+
                /*
                 * Make sure the refs we wrote out is correct; --max-count and
                 * other limiting options could have prevented all the tips
@@ -286,7 +294,7 @@ int create_bundle(struct bundle_header *header, const char *path,
                ref_count++;
                write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
                write_or_die(bundle_fd, " ", 1);
-               write_or_die(bundle_fd, ref, strlen(ref));
+               write_or_die(bundle_fd, display_ref, strlen(display_ref));
                write_or_die(bundle_fd, "\n", 1);
                free(ref);
        }
@@ -309,19 +317,25 @@ int create_bundle(struct bundle_header *header, const char *path,
        rls.git_cmd = 1;
        if (start_command(&rls))
                return error("Could not spawn pack-objects");
+
+       /*
+        * start_command closed bundle_fd if it was > 1
+        * so set the lock fd to -1 so commit_lock_file()
+        * won't fail trying to close it.
+        */
+       lock.fd = -1;
+
        for (i = 0; i < revs.pending.nr; i++) {
                struct object *object = revs.pending.objects[i].item;
                if (object->flags & UNINTERESTING)
-                       write(rls.in, "^", 1);
-               write(rls.in, sha1_to_hex(object->sha1), 40);
-               write(rls.in, "\n", 1);
+                       write_or_die(rls.in, "^", 1);
+               write_or_die(rls.in, sha1_to_hex(object->sha1), 40);
+               write_or_die(rls.in, "\n", 1);
        }
        if (finish_command(&rls))
                return error ("pack-objects died");
-       close(bundle_fd);
-       if (!bundle_to_stdout)
-               commit_lock_file(&lock);
-       return 0;
+
+       return bundle_to_stdout ? close(bundle_fd) : commit_lock_file(&lock);
 }
 
 int unbundle(struct bundle_header *header, int bundle_fd)