git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2] remote-bzr: reuse bzrlib transports when possible

From
RHRichard Hansen <rhansen@bbn.com>
Date
Sep 8, 2013, 05:47 UTC
Message-ID
<1378619269-21991-1-git-send-email-rhansen@bbn.com>
In-Reply-To
<522C0B66.1080707@bbn.com>

Pass a list of open bzrlib.transport.Transport objects to each bzrlib function that might create a transport. This enables bzrlib to reuse existing transports when possible, avoiding multiple concurrent connections to the same remote server.

If the remote server is accessed via ssh, this fixes a couple of
problems:
  * If the user does not have keys loaded into an ssh agent, the user
    may be prompted for a password multiple times.
  * If the user is using OpenSSH and the ControlMaster setting is set
    to auto, git-remote-bzr might hang.  This is because bzrlib closes
    the multiple ssh sessions in an undefined order and might try to
    close the master ssh session before the other sessions.  The
    master ssh process will not exit until the other sessions have
    exited, causing a deadlock.  (The ssh sessions are closed in an
    undefined order because bzrlib relies on the Python garbage
    collector to trigger ssh session termination.)
Signed-off-by: Richard Hansen <rhansen@bbn.com>
---
Changes from v1:
  * add Signed-off-by line
 contrib/remote-helpers/git-remote-bzr | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
index c3a3cac..1e0044b 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -674,7 +674,7 @@ def parse_reset(parser):
     parsed_refs[ref] = mark_to_rev(from_mark)
 
 def do_export(parser):
-    global parsed_refs, dirname
+    global parsed_refs, dirname, transports
 
     parser.next()
 
@@ -699,7 +699,8 @@ def do_export(parser):
             branch.generate_revision_history(revid, marks.get_tip(name))
 
             if name in peers:
-                peer = bzrlib.branch.Branch.open(peers[name])
+                peer = bzrlib.branch.Branch.open(peers[name],
+                                                 possible_transports=transports)
                 try:
                     peer.bzrdir.push_branch(branch, revision_id=revid)
                 except bzrlib.errors.DivergedBranches:
@@ -769,25 +770,28 @@ def do_list(parser):
     print
 
 def clone(path, remote_branch):
+    global transports
     try:
-        bdir = bzrlib.bzrdir.BzrDir.create(path)
+        bdir = bzrlib.bzrdir.BzrDir.create(path, possible_transports=transports)
     except bzrlib.errors.AlreadyControlDirError:
-        bdir = bzrlib.bzrdir.BzrDir.open(path)
+        bdir = bzrlib.bzrdir.BzrDir.open(path, possible_transports=transports)
     repo = bdir.find_repository()
     repo.fetch(remote_branch.repository)
     return remote_branch.sprout(bdir, repository=repo)
 
 def get_remote_branch(name):
-    global dirname, branches
+    global dirname, branches, transports
 
-    remote_branch = bzrlib.branch.Branch.open(branches[name])
+    remote_branch = bzrlib.branch.Branch.open(branches[name],
+                                              possible_transports=transports)
     if isinstance(remote_branch.user_transport, bzrlib.transport.local.LocalTransport):
         return remote_branch
 
     branch_path = os.path.join(dirname, 'clone', name)
 
     try:
-        branch = bzrlib.branch.Branch.open(branch_path)
+        branch = bzrlib.branch.Branch.open(branch_path,
+                                           possible_transports=transports)
     except bzrlib.errors.NotBranchError:
         # clone
         branch = clone(branch_path, remote_branch)
@@ -821,17 +825,19 @@ def find_branches(repo):
             yield name, branch.base
 
 def get_repo(url, alias):
-    global dirname, peer, branches
+    global dirname, peer, branches, transports
 
     normal_url = bzrlib.urlutils.normalize_url(url)
-    origin = bzrlib.bzrdir.BzrDir.open(url)
+    origin = bzrlib.bzrdir.BzrDir.open(url, possible_transports=transports)
     is_local = isinstance(origin.transport, bzrlib.transport.local.LocalTransport)
 
     shared_path = os.path.join(gitdir, 'bzr')
     try:
-        shared_dir = bzrlib.bzrdir.BzrDir.open(shared_path)
+        shared_dir = bzrlib.bzrdir.BzrDir.open(shared_path,
+                                               possible_transports=transports)
     except bzrlib.errors.NotBranchError:
-        shared_dir = bzrlib.bzrdir.BzrDir.create(shared_path)
+        shared_dir = bzrlib.bzrdir.BzrDir.create(shared_path,
+                                                 possible_transports=transports)
     try:
         shared_repo = shared_dir.open_repository()
     except bzrlib.errors.NoRepositoryPresent:
@@ -844,7 +850,8 @@ def get_repo(url, alias):
         else:
             # check and remove old organization
             try:
-                bdir = bzrlib.bzrdir.BzrDir.open(clone_path)
+                bdir = bzrlib.bzrdir.BzrDir.open(clone_path,
+                                                 possible_transports=transports)
                 bdir.destroy_repository()
             except bzrlib.errors.NotBranchError:
                 pass
@@ -897,6 +904,7 @@ def main(args):
     global files_cache
     global is_tmp
     global branches, peers
+    global transports
 
     alias = args[1]
     url = args[2]
@@ -909,6 +917,7 @@ def main(args):
     marks = None
     branches = {}
     peers = {}
+    transports = []
 
     if alias[5:] == url:
         is_tmp = True
-- 
1.8.4
Previous: Richard HansenNext: Junio C Hamano
Message 5 of 10 in “remote-bzr: reuse bzrlib transports when possible”
  1. remote-bzr: reuse bzrlib transports when possibleRichard Hansen, Sep 7, 2013
  2. Richard HansenSep 8, 2013
  3. Felipe ContrerasSep 8, 2013
  4. Richard HansenSep 8, 2013
  5. remote-bzr: reuse bzrlib transports when possibleRichard Hansen, Sep 8, 2013
  6. Junio C HamanoSep 9, 2013
  7. Junio C HamanoSep 10, 2013
  8. Richard HansenSep 12, 2013
  9. Junio C HamanoSep 12, 2013
  10. Felipe ContrerasSep 8, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.