Merge pull request #2763 from libgit2/cmn/local-proto-progress Show progress output on fetch for the local transport
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
diff --git a/src/transports/local.c b/src/transports/local.c
index 3846f06..d698e01 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -35,6 +35,9 @@ typedef struct {
int flags;
git_atomic cancelled;
git_repository *repo;
+ git_transport_message_cb progress_cb;
+ git_transport_message_cb error_cb;
+ void *message_cb_payload;
git_vector refs;
unsigned connected : 1,
have_refs : 1;
@@ -494,6 +497,8 @@ static int foreach_cb(void *buf, size_t len, void *payload)
return data->writepack->append(data->writepack, buf, len, data->stats);
}
+static const char *counting_objects_fmt = "Counting objects %d\r";
+
static int local_download_pack(
git_transport *transport,
git_repository *repo,
@@ -510,6 +515,7 @@ static int local_download_pack(
git_packbuilder *pack = NULL;
git_odb_writepack *writepack = NULL;
git_odb *odb = NULL;
+ git_buf progress_info = GIT_BUF_INIT;
if ((error = git_revwalk_new(&walk, t->repo)) < 0)
goto cleanup;
@@ -540,6 +546,13 @@ static int local_download_pack(
git_object_free(obj);
}
+ if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
+ goto cleanup;
+
+ if (t->progress_cb &&
+ (error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0)
+ goto cleanup;
+
/* Walk the objects, building a packfile */
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
goto cleanup;
@@ -561,9 +574,28 @@ static int local_download_pack(
}
git_commit_free(commit);
+
+ git_buf_clear(&progress_info);
+ if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
+ goto cleanup;
+
+ if (t->progress_cb &&
+ (error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0)
+ goto cleanup;
+
}
}
+ /* One last one with the newline */
+ git_buf_clear(&progress_info);
+ git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack));
+ if ((error = git_buf_putc(&progress_info, '\n')) < 0)
+ goto cleanup;
+
+ if (t->progress_cb &&
+ (error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0)
+ goto cleanup;
+
if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)
goto cleanup;
@@ -582,11 +614,30 @@ static int local_download_pack(
cleanup:
if (writepack) writepack->free(writepack);
+ git_buf_free(&progress_info);
git_packbuilder_free(pack);
git_revwalk_free(walk);
return error;
}
+static int local_set_callbacks(
+ git_transport *transport,
+ git_transport_message_cb progress_cb,
+ git_transport_message_cb error_cb,
+ git_transport_certificate_check_cb certificate_check_cb,
+ void *message_cb_payload)
+{
+ transport_local *t = (transport_local *)transport;
+
+ GIT_UNUSED(certificate_check_cb);
+
+ t->progress_cb = progress_cb;
+ t->error_cb = error_cb;
+ t->message_cb_payload = message_cb_payload;
+
+ return 0;
+}
+
static int local_is_connected(git_transport *transport)
{
transport_local *t = (transport_local *)transport;
@@ -656,6 +707,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
GITERR_CHECK_ALLOC(t);
t->parent.version = GIT_TRANSPORT_VERSION;
+ t->parent.set_callbacks = local_set_callbacks;
t->parent.connect = local_connect;
t->parent.negotiate_fetch = local_negotiate_fetch;
t->parent.download_pack = local_download_pack;
diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c
index 736261b..b78253d 100644
--- a/tests/network/fetchlocal.c
+++ b/tests/network/fetchlocal.c
@@ -162,3 +162,37 @@ void test_network_fetchlocal__multi_remotes(void)
git_remote_free(test);
git_remote_free(test2);
}
+
+static int sideband_cb(const char *str, int len, void *payload)
+{
+ int *count = (int *) payload;
+
+ GIT_UNUSED(str);
+ GIT_UNUSED(len);
+
+ (*count)++;
+ return 0;
+}
+
+void test_network_fetchlocal__call_progress(void)
+{
+ git_repository *repo;
+ git_remote *remote;
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
+ int callcount = 0;
+
+ cl_git_pass(git_repository_init(&repo, "foo.git", true));
+ cl_set_cleanup(cleanup_local_repo, "foo.git");
+
+ cl_git_pass(git_remote_create_with_fetchspec(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"), "+refs/heads/*:refs/heads/*"));
+
+ callbacks.sideband_progress = sideband_cb;
+ callbacks.payload = &callcount;
+ cl_git_pass(git_remote_set_callbacks(remote, &callbacks));
+
+ cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
+ cl_assert(callcount != 0);
+
+ git_remote_free(remote);
+ git_repository_free(repo);
+}