summaryrefslogtreecommitdiff
path: root/examples/network/fetch.c
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlos@cmartin.tk>2011-10-03 00:33:13 +0200
committerCarlos Martín Nieto <carlos@cmartin.tk>2011-10-03 02:32:32 +0200
commit2401262778fa50cea30d1988cec45dcb82b50712 (patch)
tree80adb600f2bb02c941314dc725706827890e07c9 /examples/network/fetch.c
parentcd19ca9584bd01925e05e94e7f3bddae6880acda (diff)
downloadlibgit2-2401262778fa50cea30d1988cec45dcb82b50712.tar.gz
examples: add ls-remote, fetch and index-pack examples
Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
Diffstat (limited to 'examples/network/fetch.c')
-rw-r--r--examples/network/fetch.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/examples/network/fetch.c b/examples/network/fetch.c
new file mode 100644
index 000000000..dd732f22e
--- /dev/null
+++ b/examples/network/fetch.c
@@ -0,0 +1,127 @@
+#include "common.h"
+#include <git2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void show_refs(git_headarray *refs)
+{
+ int i;
+ git_remote_head *head;
+
+ if(refs->len == 0)
+ puts("Everything up-to-date");
+
+ for(i = 0; i < refs->len; ++i){
+ char oid[GIT_OID_HEXSZ + 1] = {0};
+ char *havewant;
+ head = refs->heads[i];
+ git_oid_fmt(oid, &head->oid);
+ printf("%s\t%s\n", oid, head->name);
+ }
+}
+
+static int rename_packfile(char *packname, git_indexer *idx)
+{
+ char path[GIT_PATH_MAX], oid[GIT_OID_HEXSZ + 1], *slash;
+ int ret;
+
+ strcpy(path, packname);
+ slash = strrchr(path, '/');
+
+ if (!slash)
+ return GIT_EINVALIDARGS;
+
+ memset(oid, 0x0, sizeof(oid));
+ // The name of the packfile is given by it's hash which you can get
+ // with git_indexer_hash after the index has been written out to
+ // disk. Rename the packfile to its "real" name in the same
+ // directory as it was originally (libgit2 stores it in the folder
+ // where the packs go, so a rename in place is the right thing to do here
+ git_oid_fmt(oid, git_indexer_hash(idx));
+ ret = sprintf(slash + 1, "pack-%s.pack", oid);
+ if(ret < 0)
+ return GIT_EOSERR;
+
+ printf("Renaming pack to %s\n", path);
+ return rename(packname, path);
+}
+
+int fetch(git_repository *repo, int argc, char **argv)
+{
+ git_remote *remote = NULL;
+ git_config *cfg = NULL;
+ git_indexer *idx = NULL;
+ git_indexer_stats stats;
+ int error;
+ char *packname = NULL;
+
+ // Load the repository's configuration
+ error = git_repository_config(&cfg, repo, NULL, NULL);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ // Get the remote and connect to it
+ printf("Fetching %s\n", argv[1]);
+ error = git_remote_get(&remote, cfg, argv[1]);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ error = git_remote_connect(remote, GIT_DIR_FETCH);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ // Perform the packfile negotiation. This is where the two ends
+ // figure out the minimal amount of data that should be transmitted
+ // to bring the repository up-to-date
+ error = git_remote_negotiate(remote);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ // Download the packfile from the server. As we don't know its hash
+ // yet, it will get a temporary filename
+ error = git_remote_download(&packname, remote);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ // No error and a NULL packname means no packfile was needed
+ if (packname != NULL) {
+ printf("The packname is %s\n", packname);
+
+ // Create a new instance indexer
+ error = git_indexer_new(&idx, packname);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ // This should be run in paralel, but it'd be too complicated for the example
+ error = git_indexer_run(idx, &stats);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ printf("Received %d objects\n", stats.total);
+
+ // Write the index file. The index will be stored with the
+ // correct filename
+ error = git_indexer_write(idx);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ error = rename_packfile(packname, idx);
+ if (error < GIT_SUCCESS)
+ return error;
+ }
+
+ // Update the references in the remote's namespace to point to the
+ // right commits. This may be needed even if there was no packfile
+ // to download, which can happen e.g. when the branches have been
+ // changed but all the neede objects are available locally.
+ error = git_remote_update_tips(remote);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ free(packname);
+ git_indexer_free(idx);
+ git_remote_free(remote);
+
+ return GIT_SUCCESS;
+}