Merge branch 'svnup' of http://netz.smurf.noris.de/git/git
authorJunio C Hamano <junkio@cox.net>
Mon, 14 Nov 2005 21:50:05 +0000 (13:50 -0800)
committerJunio C Hamano <junkio@cox.net>
Mon, 14 Nov 2005 21:50:05 +0000 (13:50 -0800)
Signed-off-by: Junio C Hamano <junkio@cox.net>
15 files changed:
.gitignore
Documentation/git-lost+found.txt [deleted file]
Documentation/git-lost-found.txt [new file with mode: 0644]
Documentation/git-rename.txt [deleted file]
Documentation/git.txt
Makefile
debian/changelog
debian/control
git-clone.sh
git-core.spec.in
git-lost+found.sh [deleted file]
git-lost-found.sh [new file with mode: 0755]
git-rename.perl [deleted file]
http-fetch.c
pack-redundant.c

index 328b399..0dd7b9c 100644 (file)
@@ -42,7 +42,7 @@ git-index-pack
 git-init-db
 git-local-fetch
 git-log
-git-lost+found
+git-lost-found
 git-ls-files
 git-ls-remote
 git-ls-tree
@@ -74,7 +74,6 @@ git-read-tree
 git-rebase
 git-receive-pack
 git-relink
-git-rename
 git-repack
 git-request-pull
 git-reset
diff --git a/Documentation/git-lost+found.txt b/Documentation/git-lost+found.txt
deleted file mode 100644 (file)
index a8cc573..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-git-lost+found(1)
-=================
-
-NAME
-----
-git-lost+found - Recover lost refs that luckily have not yet been pruned.
-
-SYNOPSIS
---------
-'git-lost+found'
-
-DESCRIPTION
------------
-Finds dangling commits and tags from the object database, and
-creates refs to them in .git/lost-found/ directory.  Commits and
-tags that dereference to commits go to .git/lost-found/commit
-and others are stored in .git/lost-found/other directory.
-
-
-OUTPUT
-------
-One line description from the commit and tag found along with
-their object name are printed on the standard output.
-
-
-EXAMPLE
--------
-
-Suppose you run 'git tag -f' and mistyped the tag to overwrite.
-The ref to your tag is overwritten, but until you run 'git
-prune', it is still there.
-
-------------
-$ git lost+found
-[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
-...
-------------
-
-Also you can use gitk to browse how they relate to each other
-and existing (probably old) tags.
-
-------------
-$ gitk $(cd .git/lost-found/commit && echo ??*)
-------------
-
-After making sure that it is the object you are looking for, you
-can reconnect it to your regular .git/refs hierarchy.
-
-------------
-$ git cat-file -t 1ef2b196
-tag
-$ git cat-file tag 1ef2b196
-object fa41bbce8e38c67a218415de6cfa510c7e50032a
-type commit
-tag v0.99.9c
-tagger Junio C Hamano <junkio@cox.net> 1131059594 -0800
-
-GIT 0.99.9c
-
-This contains the following changes from the "master" branch, since
-...
-$ git update-ref refs/tags/not-lost-anymore 1ef2b196
-$ git rev-parse not-lost-anymore
-1ef2b196d909eed523d4f3c9bf54b78cdd6843c6
-------------
-
-Author
-------
-Written by Junio C Hamano 濱野 純 <junkio@cox.net>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-
-GIT
----
-Part of the gitlink:git[7] suite
diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt
new file mode 100644 (file)
index 0000000..03156f2
--- /dev/null
@@ -0,0 +1,78 @@
+git-lost-found(1)
+=================
+
+NAME
+----
+git-lost-found - Recover lost refs that luckily have not yet been pruned.
+
+SYNOPSIS
+--------
+'git-lost-found'
+
+DESCRIPTION
+-----------
+Finds dangling commits and tags from the object database, and
+creates refs to them in .git/lost-found/ directory.  Commits and
+tags that dereference to commits go to .git/lost-found/commit
+and others are stored in .git/lost-found/other directory.
+
+
+OUTPUT
+------
+One line description from the commit and tag found along with
+their object name are printed on the standard output.
+
+
+EXAMPLE
+-------
+
+Suppose you run 'git tag -f' and mistyped the tag to overwrite.
+The ref to your tag is overwritten, but until you run 'git
+prune', it is still there.
+
+------------
+$ git lost-found
+[1ef2b196d909eed523d4f3c9bf54b78cdd6843c6] GIT 0.99.9c
+...
+------------
+
+Also you can use gitk to browse how they relate to each other
+and existing (probably old) tags.
+
+------------
+$ gitk $(cd .git/lost-found/commit && echo ??*)
+------------
+
+After making sure that it is the object you are looking for, you
+can reconnect it to your regular .git/refs hierarchy.
+
+------------
+$ git cat-file -t 1ef2b196
+tag
+$ git cat-file tag 1ef2b196
+object fa41bbce8e38c67a218415de6cfa510c7e50032a
+type commit
+tag v0.99.9c
+tagger Junio C Hamano <junkio@cox.net> 1131059594 -0800
+
+GIT 0.99.9c
+
+This contains the following changes from the "master" branch, since
+...
+$ git update-ref refs/tags/not-lost-anymore 1ef2b196
+$ git rev-parse not-lost-anymore
+1ef2b196d909eed523d4f3c9bf54b78cdd6843c6
+------------
+
+Author
+------
+Written by Junio C Hamano 濱野 純 <junkio@cox.net>
+
+Documentation
+--------------
+Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+
+GIT
+---
+Part of the gitlink:git[7] suite
diff --git a/Documentation/git-rename.txt b/Documentation/git-rename.txt
deleted file mode 100644 (file)
index 583cb03..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-git-rename(1)
-=============
-
-NAME
-----
-git-rename - Script used to rename a file, directory or symlink.
-
-
-SYNOPSIS
---------
-'git-rename' <source> <destination>
-
-DESCRIPTION
------------
-This script is used to rename a file, directory or symlink.
-
-The index is updated after successful completion, but the change must still be
-committed.
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-Rewritten by Ryan Anderson <ryan@michonline.com>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
index a9d47c1..7045f3f 100644 (file)
@@ -262,9 +262,6 @@ gitlink:git-push[1]::
 gitlink:git-rebase[1]::
        Rebase local commits to new upstream head.
 
-gitlink:git-rename[1]::
-       Rename files and directories.
-
 gitlink:git-repack[1]::
        Pack unpacked objects in a repository.
 
@@ -309,7 +306,7 @@ gitlink:git-convert-objects[1]::
 gitlink:git-cvsimport[1]::
        Salvage your data out of another SCM people love to hate.
 
-gitlink:git-lost+found[1]::
+gitlink:git-lost-found[1]::
        Recover lost refs that luckily have not yet been pruned.
 
 gitlink:git-merge-one-file[1]::
index b75cb13..63cb998 100644 (file)
--- a/Makefile
+++ b/Makefile
 
 GIT_VERSION = 0.99.9.GIT
 
-# CFLAGS is for the users to override from the command line.
+# CFLAGS and LDFLAGS are for the users to override from the command line.
 
 CFLAGS = -g -O2 -Wall
+LDFLAGS =
 ALL_CFLAGS = $(CFLAGS)
+ALL_LDFLAGS = $(LDFLAGS)
 
 prefix = $(HOME)
 bindir = $(prefix)/bin
@@ -90,11 +92,11 @@ SCRIPT_SH = \
        git-applymbox.sh git-applypatch.sh git-am.sh \
        git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
        git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
-       git-lost+found.sh
+       git-lost-found.sh
 
 SCRIPT_PERL = \
        git-archimport.perl git-cvsimport.perl git-relink.perl \
-       git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
+       git-shortlog.perl git-fmt-merge-msg.perl \
        git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
 
 SCRIPT_PYTHON = \
@@ -187,9 +189,11 @@ ifeq ($(uname_S),Darwin)
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
        ## fink
-       ALL_CFLAGS += -I/sw/include -L/sw/lib
+       ALL_CFLAGS += -I/sw/include
+       ALL_LDFLAGS += -L/sw/lib
        ## darwinports
-       ALL_CFLAGS += -I/opt/local/include -L/opt/local/lib
+       ALL_CFLAGS += -I/opt/local/include
+       ALL_LDFLAGS += -L/opt/local/lib
 endif
 ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
@@ -211,7 +215,13 @@ endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
        NEEDS_LIBICONV = YesPlease
-       ALL_CFLAGS += -I/usr/local/include -L/usr/local/lib
+       ALL_CFLAGS += -I/usr/local/include
+       ALL_LDFLAGS += -L/usr/local/lib
+endif
+ifeq ($(uname_S),NetBSD)
+       NEEDS_LIBICONV = YesPlease
+       ALL_CFLAGS += -I/usr/pkg/include
+       ALL_LDFLAGS += -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
 endif
 ifneq (,$(findstring arm,$(uname_M)))
        ARM_SHA1 = YesPlease
@@ -221,7 +231,7 @@ endif
 
 ifndef NO_CURL
        ifdef CURLDIR
-               # This is still problematic -- gcc does not want -R.
+               # This is still problematic -- gcc does not always want -R.
                ALL_CFLAGS += -I$(CURLDIR)/include
                CURL_LIBCURL = -L$(CURLDIR)/lib -R$(CURLDIR)/lib -lcurl
        else
@@ -369,12 +379,13 @@ git-cherry-pick: git-revert
        $(CC) -o $*.o -c $(ALL_CFLAGS) $<
 
 git-%$X: %.o $(LIB_FILE)
-       $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
+       $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
 git-mailinfo$X : SIMPLE_LIB += $(LIB_4_ICONV)
 $(SIMPLE_PROGRAMS) : $(LIB_FILE)
 $(SIMPLE_PROGRAMS) : git-%$X : %.o
-       $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB)
+       $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+               $(LIB_FILE) $(SIMPLE_LIB)
 
 git-http-fetch$X: fetch.o
 git-local-fetch$X: fetch.o
@@ -408,10 +419,10 @@ test: all
        $(MAKE) -C t/ all
 
 test-date$X: test-date.c date.o ctype.o
-       $(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o ctype.o
+       $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) test-date.c date.o ctype.o
 
 test-delta$X: test-delta.c diff-delta.o patch-delta.o
-       $(CC) $(ALL_CFLAGS) -o $@ $^
+       $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
 
 check:
        for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i; done
index 10f67b8..376f0fa 100644 (file)
@@ -1,3 +1,9 @@
+git-core (0.99.9.GIT-2) unstable; urgency=low
+
+  * Build Dependency did not include libexpat-dev.
+
+ -- Junio C Hamano <junkio@cox.net>  Sun, 13 Nov 2005 01:55:34 -0800
+
 git-core (0.99.9.GIT-1) unstable; urgency=low
 
   * Do not scatter txt and html documentation into feature
index 965fb62..ded0a57 100644 (file)
@@ -2,7 +2,7 @@ Source: git-core
 Section: devel
 Priority: optional
 Maintainer: Junio C Hamano <junkio@cox.net>
-Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 7), xmlto, debhelper (>= 4.0.0), bc
+Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev|libcurl3-gnutls-dev|libcurl3-openssl-dev, asciidoc (>= 7), xmlto, debhelper (>= 4.0.0), bc, libexpat-dev
 Standards-Version: 3.6.1
 
 Package: git-core
index f99e0ad..c09979a 100755 (executable)
@@ -9,7 +9,7 @@
 unset CDPATH
 
 usage() {
-       echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> <dir>"
+       echo >&2 "* git clone [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> [<dir>]"
        exit 1
 }
 
@@ -98,7 +98,7 @@ fi
 dir="$2"
 # Try using "humanish" part of source repo if user didn't specify one
 [ -z "$dir" ] && dir=$(echo "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*/||g')
-[ -e "$dir" ] && $(echo "$dir already exists."; usage)
+[ -e "$dir" ] && echo "$dir already exists." && usage
 mkdir -p "$dir" &&
 D=$(
        (cd "$dir" && git-init-db && pwd)
index 6a482ad..16c6269 100644 (file)
@@ -7,9 +7,9 @@ License:        GPL
 Group:                 Development/Tools
 URL:           http://kernel.org/pub/software/scm/git/
 Source:        http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
-BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
+BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
 BuildRoot:     %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires:      zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, tk >= 8.4
+Requires:      zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat
 
 %description
 This is a stupid (but extremely fast) directory content manager.  It
@@ -47,6 +47,13 @@ Requires:    git-core = %{version}-%{release}
 %description email
 Git tools for sending email.
 
+%package tk
+Summary:        Git revision tree visualiser ('gitk')
+Group:          Development/Tools
+Requires:       git-core = %{version}-%{release}, tk >= 8.4
+%description tk
+Git revision tree visualiser ('gitk')
+
 %prep
 %setup -q
 
@@ -60,9 +67,9 @@ make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease WIT
      prefix=%{_prefix} mandir=%{_mandir} \
      install %{!?_without_docs: install-doc}
 
-(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "arch|svn|cvs|email" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "arch|svn|cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
 %if %{!?_without_docs:1}0
-(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "arch|svn|git-cvs|email" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "arch|svn|git-cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
 %endif
 
 %clean
@@ -96,6 +103,13 @@ rm -rf $RPM_BUILD_ROOT
 %{!?_without_docs: %{_mandir}/man1/*email*.1*}
 %{!?_without_docs: %doc Documentation/*email*.html }
 
+%files tk
+%defattr(-,root,root)
+%doc Documentation/*gitk*.txt
+%{_bindir}/*gitk*
+%{!?_without_docs: %{_mandir}/man1/*gitk*.1*}
+%{!?_without_docs: %doc Documentation/*gitk*.html }
+
 %files -f bin-man-doc-files
 %defattr(-,root,root)
 %{_datadir}/git-core/
diff --git a/git-lost+found.sh b/git-lost+found.sh
deleted file mode 100755 (executable)
index 3892f52..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-. git-sh-setup || die "Not a git archive."
-
-laf="$GIT_DIR/lost-found"
-rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
-
-git fsck-objects |
-while read dangling type sha1
-do
-       case "$dangling" in
-       dangling)
-               if git-rev-parse --verify "$sha1^0" >/dev/null 2>/dev/null
-               then
-                       dir="$laf/commit"
-                       git-show-branch "$sha1"
-               else
-                       dir="$laf/other"
-               fi
-               echo "$sha1" >"$dir/$sha1"
-               ;;
-       esac
-done
diff --git a/git-lost-found.sh b/git-lost-found.sh
new file mode 100755 (executable)
index 0000000..3892f52
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+. git-sh-setup || die "Not a git archive."
+
+laf="$GIT_DIR/lost-found"
+rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
+
+git fsck-objects |
+while read dangling type sha1
+do
+       case "$dangling" in
+       dangling)
+               if git-rev-parse --verify "$sha1^0" >/dev/null 2>/dev/null
+               then
+                       dir="$laf/commit"
+                       git-show-branch "$sha1"
+               else
+                       dir="$laf/other"
+               fi
+               echo "$sha1" >"$dir/$sha1"
+               ;;
+       esac
+done
diff --git a/git-rename.perl b/git-rename.perl
deleted file mode 100755 (executable)
index 3b1127b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/perl
-#
-# Copyright 2005, Ryan Anderson <ryan@michonline.com>
-#
-# This file is licensed under the GPL v2, or a later version
-# at the discretion of Linus Torvalds.
-
-
-use warnings;
-use strict;
-
-sub usage($);
-
-# Sanity checks:
-my $GIT_DIR = $ENV{'GIT_DIR'} || ".git";
-
-unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && 
-       -d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") {
-       usage("Git repository not found.");
-}
-
-usage("") if scalar @ARGV != 2;
-
-my ($src,$dst) = @ARGV;
-
-unless (-f $src || -l $src || -d $src) {
-       usage("git rename: bad source '$src'");
-}
-
-if (-e $dst) {
-       usage("git rename: destinations '$dst' already exists");
-}
-
-my (@allfiles,@srcfiles,@dstfiles);
-
-$/ = "\0";
-open(F,"-|","git-ls-files","-z")
-       or die "Failed to open pipe from git-ls-files: " . $!;
-
-@allfiles = map { chomp; $_; } <F>;
-close(F);
-
-my $safesrc = quotemeta($src);
-@srcfiles = grep /^$safesrc/, @allfiles;
-@dstfiles = @srcfiles;
-s#^$safesrc(/|$)#$dst$1# for @dstfiles;
-
-rename($src,$dst)
-       or die "rename failed: $!";
-
-my $rc = system("git-update-index","--add","--",@dstfiles);
-die "git-update-index failed to add new name with code $?\n" if $rc;
-
-$rc = system("git-update-index","--remove","--",@srcfiles);
-die "git-update-index failed to remove old name with code $?\n" if $rc;
-
-
-sub usage($) {
-       my $s = shift;
-       print $s, "\n" if (length $s != 0);
-       print <<EOT;
-$0 <source> <dest>
-source must exist and be either a file, symlink or directory.
-dest must NOT exist.
-
-Renames source to dest, and updates the git cache to reflect the change.
-Use "git commit" to make record the change permanently.
-EOT
-       exit(1);
-}
index f39e748..b8aa965 100644 (file)
@@ -25,7 +25,7 @@
 #define PREV_BUF_SIZE 4096
 #define RANGE_HEADER_SIZE 30
 
-static int got_alternates = 0;
+static int got_alternates = -1;
 static int active_requests = 0;
 static int data_received;
 
@@ -87,9 +87,19 @@ struct active_request_slot
        int done;
        CURLcode curl_result;
        long http_code;
+       void *callback_data;
+       void (*callback_func)(void *data);
        struct active_request_slot *next;
 };
 
+struct alt_request {
+       char *base;
+       char *url;
+       struct buffer *buffer;
+       struct active_request_slot *slot;
+       int http_specific;
+};
+
 static struct transfer_request *request_queue_head = NULL;
 static struct active_request_slot *active_queue_head = NULL;
 
@@ -237,7 +247,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
 static void process_curl_messages(void);
 static void process_request_queue(void);
 #endif
-static int fetch_alternates(char *base);
+static void fetch_alternates(char *base);
 
 static CURL* get_curl_handle(void)
 {
@@ -324,6 +334,8 @@ static struct active_request_slot *get_active_slot(void)
        slot->in_use = 1;
        slot->done = 0;
        slot->local = NULL;
+       slot->callback_data = NULL;
+       slot->callback_func = NULL;
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
@@ -601,6 +613,12 @@ static void process_curl_messages(void)
                        } else {
                                fprintf(stderr, "Received DONE message for unknown request!\n");
                        }
+
+                       /* Process slot callback if appropriate */
+                       if (slot->callback_func != NULL) {
+                               slot->callback_func(slot->callback_data);
+                       }
+
                        if (request != NULL) {
                                request->curl_result = curl_result;
                                request->http_code = slot->http_code;
@@ -614,6 +632,8 @@ static void process_curl_messages(void)
                                                request->repo =
                                                        request->repo->next;
                                                start_request(request);
+                                       } else {
+                                               finish_request(request);
                                        }
                                } else {
                                        finish_request(request);
@@ -766,72 +786,51 @@ static int setup_index(struct alt_base *repo, unsigned char *sha1)
        return 0;
 }
 
-static int fetch_alternates(char *base)
+static void process_alternates(void *callback_data)
 {
-       int ret = 0;
-       struct buffer buffer;
-       char *url;
-       char *data;
-       int i = 0;
-       int http_specific = 1;
+       struct alt_request *alt_req = (struct alt_request *)callback_data;
+       struct active_request_slot *slot = alt_req->slot;
        struct alt_base *tail = alt;
+       char *base = alt_req->base;
        static const char null_byte = '\0';
+       char *data;
+       int i = 0;
 
-       struct active_request_slot *slot;
-
-       if (got_alternates)
-               return 0;
-
-       data = xmalloc(4096);
-       buffer.size = 4096;
-       buffer.posn = 0;
-       buffer.buffer = data;
-
-       if (get_verbosely)
-               fprintf(stderr, "Getting alternates list for %s\n", base);
-       
-       url = xmalloc(strlen(base) + 31);
-       sprintf(url, "%s/objects/info/http-alternates", base);
-
-       slot = get_active_slot();
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
-                        fwrite_buffer_dynamic);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (slot->curl_result != CURLE_OK || !buffer.posn) {
-                       http_specific = 0;
-
-                       sprintf(url, "%s/objects/info/alternates", base);
-
-                       slot = get_active_slot();
-                       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-                       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
-                                        fwrite_buffer_dynamic);
-                       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+       if (alt_req->http_specific) {
+               if (slot->curl_result != CURLE_OK ||
+                   !alt_req->buffer->posn) {
+
+                       /* Try reusing the slot to get non-http alternates */
+                       alt_req->http_specific = 0;
+                       sprintf(alt_req->url, "%s/objects/info/alternates",
+                               base);
+                       curl_easy_setopt(slot->curl, CURLOPT_URL,
+                                        alt_req->url);
+                       active_requests++;
+                       slot->in_use = 1;
+                       slot->done = 0;
                        if (start_active_slot(slot)) {
-                               run_active_slot(slot);
-                               if (slot->curl_result != CURLE_OK) {
-                                       free(buffer.buffer);
-                                       if (slot->http_code == 404)
-                                               got_alternates = 1;
-                                       return 0;
-                               }
+                               return;
+                       } else {
+                               got_alternates = -1;
+                               slot->done = 1;
+                               return;
                        }
                }
-       } else {
-               free(buffer.buffer);
-               return 0;
+       } else if (slot->curl_result != CURLE_OK) {
+               if (slot->http_code != 404) {
+                       got_alternates = -1;
+                       return;
+               }
        }
 
-       fwrite_buffer_dynamic(&null_byte, 1, 1, &buffer);
-       buffer.posn--;
-       data = buffer.buffer;
+       fwrite_buffer_dynamic(&null_byte, 1, 1, alt_req->buffer);
+       alt_req->buffer->posn--;
+       data = alt_req->buffer->buffer;
 
-       while (i < buffer.posn) {
+       while (i < alt_req->buffer->posn) {
                int posn = i;
-               while (posn < buffer.posn && data[posn] != '\n')
+               while (posn < alt_req->buffer->posn && data[posn] != '\n')
                        posn++;
                if (data[posn] == '\n') {
                        int okay = 0;
@@ -855,7 +854,7 @@ static int fetch_alternates(char *base)
                                // If the server got removed, give up.
                                okay = strchr(base, ':') - base + 3 < 
                                        serverlen;
-                       } else if (http_specific) {
+                       } else if (alt_req->http_specific) {
                                char *colon = strchr(data + i, ':');
                                char *slash = strchr(data + i, '/');
                                if (colon && slash && colon < data + posn &&
@@ -881,15 +880,74 @@ static int fetch_alternates(char *base)
                                while (tail->next != NULL)
                                        tail = tail->next;
                                tail->next = newalt;
-                               ret++;
                        }
                }
                i = posn + 1;
        }
 
        got_alternates = 1;
-       free(buffer.buffer);
-       return ret;
+}
+
+static void fetch_alternates(char *base)
+{
+       struct buffer buffer;
+       char *url;
+       char *data;
+       struct active_request_slot *slot;
+       static struct alt_request alt_req;
+       int num_transfers;
+
+       /* If another request has already started fetching alternates,
+          wait for them to arrive and return to processing this request's
+          curl message */
+       while (got_alternates == 0) {
+               curl_multi_perform(curlm, &num_transfers);
+               process_curl_messages();
+               process_request_queue();
+       }
+
+       /* Nothing to do if they've already been fetched */
+       if (got_alternates == 1)
+               return;
+
+       /* Start the fetch */
+       got_alternates = 0;
+
+       data = xmalloc(4096);
+       buffer.size = 4096;
+       buffer.posn = 0;
+       buffer.buffer = data;
+
+       if (get_verbosely)
+               fprintf(stderr, "Getting alternates list for %s\n", base);
+       
+       url = xmalloc(strlen(base) + 31);
+       sprintf(url, "%s/objects/info/http-alternates", base);
+
+       /* Use a callback to process the result, since another request
+          may fail and need to have alternates loaded before continuing */
+       slot = get_active_slot();
+       slot->callback_func = process_alternates;
+       slot->callback_data = &alt_req;
+
+       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
+                        fwrite_buffer_dynamic);
+       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+
+       alt_req.base = base;
+       alt_req.url = url;
+       alt_req.buffer = &buffer;
+       alt_req.http_specific = 1;
+       alt_req.slot = slot;
+
+       if (start_active_slot(slot))
+               run_active_slot(slot);
+       else
+               got_alternates = -1;
+
+       free(data);
+       free(url);
 }
 
 static int fetch_indices(struct alt_base *repo)
index 1f8c577..28b82ee 100644 (file)
@@ -593,19 +593,20 @@ int main(int argc, char **argv)
 
        minimize(&min);
        if (verbose) {
-               fprintf(stderr, "There are %ld packs available in alt-odbs.\n",
-                       pack_list_size(altodb_packs));
+               fprintf(stderr, "There are %lu packs available in alt-odbs.\n",
+                       (unsigned long)pack_list_size(altodb_packs));
                fprintf(stderr, "The smallest (bytewise) set of packs is:\n");
                pl = min;
                while (pl) {
                        fprintf(stderr, "\t%s\n", pl->pack->pack_name);
                        pl = pl->next;
                }
-               fprintf(stderr, "containing %ld duplicate objects "
-                               "with a total size of %ldkb.\n",
-                       get_pack_redundancy(min), pack_set_bytecount(min)/1024);
-               fprintf(stderr, "A total of %ld unique objects were considered.\n",
-                       all_objects->size);
+               fprintf(stderr, "containing %lu duplicate objects "
+                               "with a total size of %lukb.\n",
+                       (unsigned long)get_pack_redundancy(min),
+                       (unsigned long)pack_set_bytecount(min)/1024);
+               fprintf(stderr, "A total of %lu unique objects were considered.\n",
+                       (unsigned long)all_objects->size);
                fprintf(stderr, "Redundant packs (with indexes):\n");
        }
        pl = red = pack_list_difference(local_packs, min);