Commit 42ea35c06157a5c75cfd20e8fe3a813140c26485

Michael Schubert 2012-05-01T22:25:43

remote: don't free transport on disconnect Currently, git_remote_disconnect not only closes the connection but also frees the underlying transport object, making it impossible to write code like // fetch stuff git_remote_download() // close connection git_remote_disconnect() // call user provided callback for each ref git_remote_update_tips(remote, callback) because remote->refs points to references owned by the transport object. This means, we have an idling connection while running the callback for each reference. Instead, allow immediate disconnect and free the transport later in git_remote_free().

diff --git a/examples/network/fetch.c b/examples/network/fetch.c
index d4a3974..23046bd 100644
--- a/examples/network/fetch.c
+++ b/examples/network/fetch.c
@@ -93,6 +93,9 @@ int fetch(git_repository *repo, int argc, char **argv)
   } while (!data.finished);
   printf("\rReceived %d/%d objects in %d bytes\n", stats.processed, stats.total, bytes);
 
+  // Disconnect the underlying connection to prevent from idling.
+  git_remote_disconnect(remote);
+
   // 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
diff --git a/src/remote.c b/src/remote.c
index 71cb627..98c2569 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -381,13 +381,8 @@ void git_remote_disconnect(git_remote *remote)
 {
 	assert(remote);
 
-	if (remote->transport != NULL) {
-		if (remote->transport->connected)
+	if (remote->transport != NULL && remote->transport->connected)
 			remote->transport->close(remote->transport);
-
-		remote->transport->free(remote->transport);
-		remote->transport = NULL;
-	}
 }
 
 void git_remote_free(git_remote *remote)
@@ -395,14 +390,21 @@ void git_remote_free(git_remote *remote)
 	if (remote == NULL)
 		return;
 
+	if (remote->transport != NULL) {
+		git_remote_disconnect(remote);
+
+		remote->transport->free(remote->transport);
+		remote->transport = NULL;
+	}
+
+	git_vector_free(&remote->refs);
+
 	git__free(remote->fetch.src);
 	git__free(remote->fetch.dst);
 	git__free(remote->push.src);
 	git__free(remote->push.dst);
 	git__free(remote->url);
 	git__free(remote->name);
-	git_vector_free(&remote->refs);
-	git_remote_disconnect(remote);
 	git__free(remote);
 }