Forum Archive

git clone ssh failing

mstonespeedy

Hey, everyone. I'm new to Pythonista, and anxious to see what it can do!

I'm just about ready to grab some scripts from our company git repository to play with. I am successfully connecting to our company Git server through ssh. However, about 6 seconds after I try a git clone ssh://..., I get the error:

stash: <class 'dulwich.errors.HangupException'>: The remote server unexpectedly closed the connection.

The server logs show a successful session open, but they don't show a session close message until 3 minutes later, so it seems to be an issue with stash/ssh/dulwich.

StaSh v0.6.15
dulwich 0.12.2

Any ideas?

JonB

Hi, how did you create your keys? The gh command has a command to create a ssh key and link it to github. while github can support 4096 bit keys, I think I had trouble with paramiko and 4096 bit.

Someone else recently had the hangup issue. @simcitywok i think, and i think he solved it by reinstalling dulwich. Also, make sure you have a solid connection -- this means the server dropped the connection unexpectedly. You might try running the command multiple times in a row, to see if you can get a valid connection.

Second, try deleting dulwich from site packages, then force quit pythonista. Then try running git again, which will download dulwich again.

Note we use a special custom version of dulwich, so if you installed yours yourself, that is a problem. Let the git command install it.

ssh on stash is pretty slow, so the initial clone might be problematic, since it has to download the entire history. You might try using https for the initial clone, then ssh subsequently.

mstonespeedy

Thanks for your help, @JonB.

I got this far following your very helpful post at https://forum.omz-software.com/topic/1848/working-copy-integration-sidebar/42. So, I used the following to generate the keys:

ssh-keygen -t rsa -b 2048

And I saw the hangup issue @SimCityWok was having, so I've done multiple retries with no success. Each time I try, it fails within 6 seconds. I've tried https, but it gives the same error.

I've now deleted dulwich and allowed git to reinstall it, but there's no difference in behavior.

I'm successfully connecting to the server via ssh, so that part of it is working properly. Wouldn't the problem be in dulwich, then?

JonB

Are you able to run ssh directly and connect / comm with the server? (if you have an account with terminal access). That would distinguish between a dulwich and paramiko problem.

Can you verify the paramiko version you are using? Likely you need 1.16.

Are you able to try https, at least for the initial clone?

Another check, trying ssh with a small repo:

[~/Documents]$ mkdir blah
[~/Documents]$ cd blah
[blah]$ git init .
[blah]$ git commit blah blah blah 
d8192599eff9eab370a6c2052b74a4d03419a59c
[blah]$ git branch
* masterd819259
[blah]$ git branch blah 
[blah]$ git checkout blah
[blah]$ git branch -D master
deletemaster['master']False
removing master (was d8192599eff9eab370a6c2052b74a4d03419a59c)
[blah]$ git remote origin ssh://yourserver
[blah]$ git push

(if you have the ability to create a new repo, that would be simpler and safer, the above is to try to avoid nuking master, by creating a new, empty branch, then pushing that... though if you can create a new repo, try cloning a repo with only 1 commit.)

If that works, then the issue is maybe just the big initial clone. try git fetch, or use https for initial clone.

if maybe the large clone is the issue: try:
git init somefolder
cd somefolder
git branch -c newbranch
echo test>test.txt
git add test.txt

git remote origin ssh://yourserver
mstonespeedy

Thanks again for your help, @JonB.

Yes, I'm able to connect to the server via ssh and run commands there. That's why I'm assuming it's a dulwich problem.

I have verified that I have paramiko 1.16.0.

No, https doesn't work either, even just for the initial clone.

Executing your sample commands gives me the same error as before ("The remote server unexpectedly closed the connection.").

Is there a way to turn on debugging messages in dulwich?

JonB

Unfortunately, this type of thing is usually prett opaque in dulwich, since the server closes the connection, and dulwich does not know why.

are you able to clone github repo's?

You could try installing the latest dulwich, then use dulwich.porcelain, (not with stash) along with pdb to try to trace through what is happening, but if you search for the specific error in dulwich.client, I think you will find there is nothing that dulwich knows about.

mstonespeedy

Thanks again for your help, @JonB. It sounds like you're confident that the problem is on the server rather than in dulwich. I'll see if I can get any other information from our server administrator.

JonB

well, no, i am not at all confident!

It would be worth installing the latest dulwich, and trying porcelain.clone().
Do the same from a pc, to isolate the problem to a dulwich one, in which case you should open an issue at the dulwich page. You might need to note what server software you are using.

mstonespeedy

I haven't tried github, but I can clone repos from our server using other clients over ssh. I'm pretty certain it's a problem with dulwich, since the server session close message is logged well after dulwich gives up. I'll log an issue on the dulwich page. Thanks again for your help!

JonB

it is a dulwich problem, but what we have to discover is whether it is a pythonista stash dulwich problem, or dulwich in general, or a problem with your specific setup.

If you can't clone from github, then we know the problem is in your setup.
If you can clone from a desktop to your server using dulwich, the problem is in the ios +dulwich combo. If you can clone using dulwich without stash, the problem is with stash git.

mstonespeedy

Makes sense, thanks. I'll do some more digging when I get a chance.

mstonespeedy

Quick update. I'm not sure when I'll have time to debug dulwich, but I wanted to at least log where I got to.

I can clone from github.

I can also clone from our company Git repository using the Working Copy iOS app with its ssh support.

mstonespeedy

I just realized that I have been working with Pythonista 2, rather than Pythonista 3. I wondered if that made a difference. So I deleted Pythonista 2 and installed Pythonista 3. The first time I did a git clone ssh, it installed dulwich for me. But as I was testing straight ssh connections, somehow dulwich was deleted. Subsequent tries of git clone ssh won't reinstall dulwich. How do I install the appropriate version of dulwich now?

dgelessus

@mstonespeedy As far as I know stash git automatically installs any missing libraries that it needs, it's not a one-time thing. Make sure that there is no dulwich in any of the three site-packages folders, then restart Pythonista to get a clean Python environment (with no cached modules), then stash should install dulwich again the next time you use git.

mstonespeedy

That's what I thought, too. But dulwich is nowhere to be found, in any of the 3 site-packages folders. I've restarted Pythonista and tried git clone ssh multiple times. I get the message:

stash: : No authentication methods available

JonB

stash by default installs the git dependencies into stash/lib.

Make sure you install your ssh keys into ~/.ssh. This might be a d fferent folder than in py2, so you may want to copy them cp ~/../.ssh ~/.ssh. I should have mentioned that while ssh looks in two places, git only looks in ~/.ssh.

JonB

Also, I will point out that stash actually uses the python2 interpreter within pythonista 3. Also, in recent beta versions, subprocess got mucked up, which breaks the exceptions that get caught in dulwich. The fix is

import subprocess
if not hasattr(subprocess,'call'):
    def Popen(*args,**kwargs):
        pass
    def call(*args,**kwargs):
        return 0
    subprocess.Popen=Popen
    subprocess.call=call

If you try using dulwich directly, just move the dulwich folder from stash/lib to site-packages, and you can then try using dulwich.porcelain.clone.That should work in either the py2 or py3 interpreter. You may need

dulwich.client.get_ssh_vendor = dulwich.client.ParamikoSSHVendor
mstonespeedy

Thanks for the additional detail, @JonB.

I did indeed need that second .ssh folder to get back where I was with Pythonista 2. And I did find the dulwich folder in stash/lib. Oh, and git.py has the ParamikoSSHVendor line. However, I'm back to the same error as before ("The remote server unexpectedly closed the connection.").

I'll try to look into the subprocess issue later today. Is Jelmer aware of it?

JonB

The subprocess issue is a pythonista issue, not dulwich. Because IOS does not let you spawn a subprocess, the newer betas commented out those parts of the standard lib (earlier versions still had all the named defined, but raised errors). dulwich imports Popen and call, but the normal workflow does not need them. (used for executing hooks, or certain type of local repositories)

BTW, in stash, you can use stashconf py_pdb 1 to enable pdb when an error is encountered. Or stashconf py_traceback 1 to print a full traceback.

You might try importing dulwich and using porcelain. There are some ways to try to request just a single branch for instance, or, say a single commit, just to see if the connection works.

mstonespeedy

Thanks for the tips, @JonB.

Has the subprocess issue been reported? I don't have a beta version of anything I'm using, as far as I know. Which files should I look for?

I tried using dulwich.porcelain.clone('ssh://user@git.myCompany.com/MyRepository.git'). I get the following error. Any ideas?

TypeError: MyRepository.git

abcabc

May be you can get workingcopy and use @ccc's scripts to sync with pythonista.
https://github.com/cclauss/Pythonista-and-Working-Copy

mstonespeedy

Thanks, @abcabc. Yes, I have Working Copy successfully cloning as I mentioned earlier. However, I'd like to see if I can get dulwich working properly, since it would be much more convenient for me.

Jelmer says that the TypeError is a known issue with Python 3, and that it is in the bug tracker. So, I may be stuck for now.

JonB

Use the python 2 interpreter -- either prepend the script with #!python2, or long press and select run with 2.7.

mstonespeedy

@JonB, I get the same TypeError with Python 2 or 3. However, if I run the Python 2 script from the command line, I get the following:

stash: : [Errno 1] Operation not permitted

Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/stash/system/shruntime.py", line 490, in exec_py_file
execfile(file_path, namespace, namespace)
File "test.py", line 6, in
dulwich.porcelain.clone('ssh://user@git.myCompany.com/MyRepository.git')
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/porcelain.py", line 258, in clone
progress=errstream.write)
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 251, in fetch
def abort():
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 557, in fetch_pack

File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 921, in _connect
raise TypeError(path)
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 877, in run_command
if port is not None:
File "/var/containers/Bundle/Application/297756CD-F73E-44E6-AB25-42E99062FE48/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/subprocess.py", line 711, in init
errread, errwrite)
File "/var/containers/Bundle/Application/297756CD-F73E-44E6-AB25-42E99062FE48/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/subprocess.py", line 1205, in _execute_child
self.pid = os.fork()
OSError: [Errno 1] Operation not permitted

JonB

Sorry, should have mentioned, after importing dulwich.client, you need to use

dulwich.client.get_ssh_vendor = dulwich.client.ParamikoSSHVendor

which tells dulwich to use paramiko instead of using the built in ssh

mstonespeedy

Thanks, @JonB. Sorry, I thought I had already done that. OK, now that I have that back in there, I'm getting the same dulwich.errors.HangupException as I started with.

Any other ideas for figuring out what's happening?

JonB

Can you find out what your company uses for a server?

Let's try going a little lower level, so we can add some logging:
https://gist.github.com/e60abaa38bd5685637e758175d7f2bda

replace source with your info.
check the resulting paramikolog.txt for any errors that might indicate a auth error, or other connection error.

In the info printed to stdout , verify that you can see the refs from the server, and see if any are successfully downloaded. (you will see a message about Counting Objects done). if so, keep running the script, and figure out which ref is causing issues.

If the first one fails, you might try changing the determine_wants to request a different ref.

Or, is your work repo using submodules? Those are not supported in the dulwich we are using, though there seems to be some pull reqs on this recently.

j

mstonespeedy

Thanks for your continued help, @JonB.

With your script, I don't get a paramikolog.txt at all. Just the same HangupException.

Our company server reports:

Ubuntu 12.04.5 LTS (GNU/Linux 3.13.0-100-generic x86_64)
git version 1.7.9.5

I don't believe we use submodules. How do I tell?

JonB

Do you get any printout from the script? I am surprised you don't get any list of refs...

Perhaps also change the paramikolog.txt to os.path.expanduser('~/Documents/paramikolog.txt')

mstonespeedy

When I run the script with your source, it creates a paramikolog.txt file just fine. But when I use my source, apparently there's nothing to write because the file is never created. And no other output on the command line. All I get is a dulwichtests/.git folder with initialized files and folders.

JonB

That is surprising, because at a minimum, you should get a "logging started" message which is logged right off the bat by my script.

Then you should see some startup stuff, and the authentication negotiation..

JonB

Can you post a full traceback of your hangup error?

mstonespeedy

stash: : The remote server unexpectedly closed the connection.

Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/stash/system/shruntime.py", line 490, in exec_py_file
execfile(file_path, namespace, namespace)
File "test_dulwich_ssh.py", line 60, in
fetch_one()
File "test_dulwich_ssh.py", line 58, in fetch_one
progress=sys.stdout.write)
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 251, in fetch
progress)
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 559, in fetch_pack
refs, server_capabilities = read_pkt_refs(proto)
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/client.py", line 168, in read_pkt_refs
for pkt in proto.read_pkt_seq():
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/protocol.py", line 201, in read_pkt_seq
pkt = self.read_pkt_line()
File "/private/var/mobile/Containers/Shared/AppGroup/E35AE39A-48FB-44A1-BC2A-EE57EF6EAA4D/Pythonista3/Documents/site-packages/dulwich/protocol.py", line 152, in read_pkt_line
raise HangupException()
HangupException: The remote server unexpectedly closed the connection.

JonB

Can you exit/restart pythonista, then run the script directly(no stash)?

Incidentally, i can reproduce this error if I type in an incorrect repo path. Are you SURE you have the full and proper path? i.e if i change uicomponents to uicomponent, i get thto same error as you.

Try adding this right after the get_transport line, around 34:

proto, can_read = client._connect(b'upload-pack', host_path)
import time
time.sleep(1.0)
okay_to_read=can_read()
while okay_to_read:
    line=proto.read_pkt_line()
    if line:
        line=line.replace('\x00','')
        print(line)
    okay_to_read=can_read()
mstonespeedy

Thanks for your additional help, @JonB.

I've been trying this URL:

'ssh://user@git.myCompany.com/git/MyRepository.git'

I did some trial and error with your test script, since can_read() was always false. I finally got it to work with an extra slash after the host name, like this:

'ssh://user@git.myCompany.com//git/MyRepository.git'

I've never had to do this with the regular git client. Do you know if there is a reason for requiring the extra slash? If not, I can report it as a bug.

Relieved to finally have it working, though. Thanks again for your patience and help!

JonB

how odd. I would report it as a dulwich issue. I suspect a true git client may do some "normalization" such as adding the .git at the end.

mstonespeedy

Will do. Thanks again.