ropensci/git2r

Struggling with pushing to GitHub

Closed this issue · 10 comments

Hi,

I'm struggling a bit with pushing to GitHub with git2r.

From ropensci/gistr#39, #43 and #116 I figured out that https remotes wouldn't work and that I needed to install libssh2, which I did with brew. I then installed git2r with

install.packages('git2r', type = 'source')

So my setup is the following one:

> library(git2r)
> libgit2_features()
$threads
[1] FALSE

$https
[1] TRUE

$ssh
[1] TRUE

> libgit2_version()
$major
[1] 0

$minor
[1] 22

$rev
[1] 0

> Sys.which('openssl')
           openssl 
"/usr/bin/openssl" 
> devtools::session_info()
Session info --------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.2.0 Patched (2015-05-18 r68382)
 system   x86_64, darwin10.8.0                       
 ui       AQUA                                       
 language (EN)                                       
 collate  en_US.UTF-8                                
 tz       America/New_York                           

Packages ------------------------------------------------------------------------------
 package   * version date       source        
 curl        0.9     2015-06-19 CRAN (R 3.2.1)
 devtools    1.8.0   2015-05-09 CRAN (R 3.2.0)
 digest      0.6.8   2014-12-31 CRAN (R 3.2.0)
 git2r     * 0.10.1  2015-05-07 CRAN (R 3.2.0)
 memoise     0.2.1   2014-04-22 CRAN (R 3.2.0)
 Rcpp        0.11.6  2015-05-01 CRAN (R 3.2.0)
 rversions   1.0.1   2015-06-06 CRAN (R 3.2.0)
 xml2        0.1.1   2015-06-02 CRAN (R 3.2.0)
> 

My GitHub account also has ssh key access configured, which is why I normally use git@ remotes.

Next, I created a test repository using the GitHub webpage, which you can see at https://github.com/lcolladotor/testgit2r. It's just an empty repository which I wanted to fill with git2r.

Locally, I create a directory, initiate the git repository, create a test file, commit it, switch the branch to gh-pages (not necessary for this issue) and attempt to push it to GitHub.

One of such attempts looks like this:

## Initiate repo
path <- '/Users/lcollado/Dropbox/Github/testgit2r'
dir.create(path)
library('git2r')
repo <- init(path)
remote_add(repo, 'origin', 'git@github.com:lcolladotor/testgit2r.git')

## Add file and switch to gh-pages branch
writeLines("Hello world!!", file.path(path, "example.txt"))
add(repo, "example.txt")
ci <- commit(repo, "Commit message")
checkout(repo, branch = 'gh-pages', create = TRUE)

## 3 different ways to try to push, taken from docs and other issues
push(repo, 'origin', 'refs/heads/gh-pages')
push(repo, 'origin', 'gh-pages')
push(repo, 'origin', "refs/heads/gh-pages:refs/heads/gh-pages")

All of these push attempts lead to the same error. Below I show one of them.

> push(repo, 'origin', 'refs/heads/gh-pages')
Error in .local(object, ...) : 
  Error in 'git2r_push': error authenticating: 
> traceback()
4: .Call(git2r_push, object, name, refspec, credentials)
3: .local(object, ...)
2: push(repo, "origin", "refs/heads/gh-pages")
1: push(repo, "origin", "refs/heads/gh-pages")

From the error, I get that my user authentication is not working. Specifying my username locally doesn't help (it's already in my global config).

> config(repo, user.name="lcolladotor", user.email="lcollado@jhsph.edu")
global:
        alias.br=branch
        alias.ci=commit
        alias.co=checkout
        alias.last=log -1 HEAD
        alias.st=status
        alias.visual=gitk
        core.editor=mate -w
        core.excludesfile=/Users/lcollado/.gitignore_global
        core.excludesfiles=/Users/lcollado/.gitignore_global
        difftool.sourcetree.cmd=opendiff "$LOCAL" "$REMOTE"
        difftool.sourcetree.path=
        mergetool.sourcetree.cmd=/Applications/SourceTree.app/Contents/Resources/opendiff-w.sh "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"
        mergetool.sourcetree.trustexitcode=true
        push.default=simple
        user.email=lcollado@jhsph.edu
        user.name=lcolladotor
local:
        core.bare=false
        core.filemode=true
        core.ignorecase=true
        core.logallrefupdates=true
        core.precomposeunicode=true
        core.repositoryformatversion=0
        remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
        remote.origin.url=git@github.com:lcolladotor/testgit2r.git
        user.email=lcollado@jhsph.edu
        user.name=lcolladotor

So, by now the obvious thing to try is to use the credentials argument to push(). However, using cred_user_pass() leads to a segfault as shown below.

> cred <- cred_user_pass('lcolladotor', 'MyPassword')
> push(repo, 'origin', 'refs/heads/gh-pages', credentials = cred)

 *** caught segfault ***
address 0x0, cause 'memory not mapped'

Traceback:
 1: .Call(git2r_push, object, name, refspec, credentials)
 2: .local(object, ...)
 3: push(repo, "origin", "refs/heads/gh-pages", credentials = cred)
 4: push(repo, "origin", "refs/heads/gh-pages", credentials = cred)

Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace

And finally, using cred_ssh_key() didn't work either.

> cred <- cred_ssh_key('~/.ssh/id_dsa.pub', '~/.ssh/id_dsa')
> push(repo, 'origin', 'refs/heads/gh-pages', credentials = cred)
Error in .local(object, ...) : 
  Error in 'git2r_push': Failed to authenticate SSH session: Waiting for USERAUTH response

Maybe for this to work I need to manually push something to the GitHub repo. That is, maybe push() doesn't work with empty repos.

I haven't tried to do all of this with Bitbucket, but I can do it if you need the info. Also note that using https remotes failed, as expected from the previously linked git2r issues.

My use case is similar to #18. I want the user to supply their credential information, and maybe the repo name. This is to complete leekgroup/regionReport#8.

Thanks for reporting the issue.

I will go through your example, investigate the segfault and see if I can make it work. I have successfully pushed to GitHub (https://github.com/stewid/playground) with git2r using ssh and an ssh-agent.

Hi @lcolladotor
I have fixed the segfault but I have not yet succeeded to push over ssh without an ssh-agent. I'm working on it.

Thanks for looking into this.

I forked your example (https://github.com/lcolladotor/playground) and attempted to use your code, but ran into the same problems as shown below.

Code as is fails at authenticating step.

> library('git2r')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground")
cloning into './playground'...
Error in clone("git@github.com:lcolladotor/playground.git", "./playground") : 
  Error in 'git2r_clone': error authenticating: 
> traceback()
3: .Call(git2r_clone, url, local_path, bare, credentials, progress)
2: clone("git@github.com:lcolladotor/playground.git", "./playground")
1: clone("git@github.com:lcolladotor/playground.git", "./playground")
> devtools::session_info()
Session info --------------------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.2.0 Patched (2015-05-18 r68382)
 system   x86_64, darwin10.8.0                       
 ui       AQUA                                       
 language (EN)                                       
 collate  en_US.UTF-8                                
 tz       America/New_York                           

Packages ------------------------------------------------------------------------------------------
 package   * version date       source        
 curl        0.9     2015-06-19 CRAN (R 3.2.1)
 devtools    1.8.0   2015-05-09 CRAN (R 3.2.0)
 digest      0.6.8   2014-12-31 CRAN (R 3.2.0)
 git2r     * 0.10.1  2015-05-07 CRAN (R 3.2.0)
 memoise     0.2.1   2014-04-22 CRAN (R 3.2.0)
 Rcpp        0.11.6  2015-05-01 CRAN (R 3.2.0)
 rversions   1.0.1   2015-06-06 CRAN (R 3.2.0)
 xml2        0.1.1   2015-06-02 CRAN (R 3.2.0)
> libgit2_features()
$threads
[1] FALSE

$https
[1] TRUE

$ssh
[1] TRUE

> 

Using cred_user_pass() leads to a segfault error.

> library('git2r')
> cred <- cred_user_pass('lcolladotor', 'MyPassword')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...

 *** caught segfault ***
address 0x0, cause 'memory not mapped'

Traceback:
 1: .Call(git2r_clone, url, local_path, bare, credentials, progress)
 2: clone("git@github.com:lcolladotor/playground.git", "./playground",     credentials = cred)
 3: clone("git@github.com:lcolladotor/playground.git", "./playground",     credentials = cred)

Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace

Using cred_ssh_key() leads to the USERAUTH response message.

> library('git2r')
> cred <- cred_ssh_key('~/.ssh/id_dsa.pub', '~/.ssh/id_dsa')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...
Error in clone("git@github.com:lcolladotor/playground.git", "./playground",  : 
  Error in 'git2r_clone': Failed to authenticate SSH session: Waiting for USERAUTH response
> traceback()
3: .Call(git2r_clone, url, local_path, bare, credentials, progress)
2: clone("git@github.com:lcolladotor/playground.git", "./playground", 
       credentials = cred)
1: clone("git@github.com:lcolladotor/playground.git", "./playground", 
       credentials = cred)
> 

Ahh, we just posted nearly at the same time. I'll try again with the latest version.

Hi again,

I'm running into the segfault issue with the latest version too as shown below.

> library('git2r')
> cred <- cred_user_pass('lcolladotor', 'MyPassword')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...

 *** caught segfault ***
address 0x0, cause 'memory not mapped'

Traceback:
 1: .Call(git2r_clone, url, local_path, bare, branch, credentials,     progress)
 2: clone("git@github.com:lcolladotor/playground.git", "./playground",     credentials = cred)
 3: clone("git@github.com:lcolladotor/playground.git", "./playground",     credentials = cred)

Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
> library('git2r')
> devtools::session_info()
Session info --------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.2.0 Patched (2015-05-18 r68382)
 system   x86_64, darwin10.8.0                       
 ui       AQUA                                       
 language (EN)                                       
 collate  en_US.UTF-8                                
 tz       America/New_York                           

Packages ------------------------------------------------------------------------------
 package   * version     date       source                         
 curl        0.9         2015-06-19 CRAN (R 3.2.1)                 
 devtools    1.8.0       2015-05-09 CRAN (R 3.2.0)                 
 digest      0.6.8       2014-12-31 CRAN (R 3.2.0)                 
 git2r     * 0.10.1.9000 2015-07-10 Github (ropensci/git2r@fcf56fd)
 memoise     0.2.1       2014-04-22 CRAN (R 3.2.0)                 
 Rcpp        0.11.6      2015-05-01 CRAN (R 3.2.0)                 
 rversions   1.0.1       2015-06-06 CRAN (R 3.2.0)                 
 xml2        0.1.1       2015-06-02 CRAN (R 3.2.0)                 
> 

For completeness. Here's the installation log for git2r.
https://gist.github.com/f05db33a120a05973680

Thanks for testing, I have fixed the segfault from clone. I have successfully cloned and pushed to GitHub with the following code.

library(git2r)
cred <- cred_ssh_key("~/.ssh/id_rsa.pub", "~/.ssh/id_rsa")
repo <- clone("git@github.com:stewid/playground.git", "playground", credentials = cred)
#> cloning into 'playground'...
#> Receiving objects:   2% (1/48),    6 kb
#> Receiving objects:  12% (6/48),    6 kb
#> Receiving objects:  22% (11/48),    6 kb
#> Receiving objects:  31% (15/48),    6 kb
#> Receiving objects:  41% (20/48),    6 kb
#> Receiving objects:  52% (25/48),    6 kb
#> Receiving objects:  62% (30/48),    6 kb
#> Receiving objects:  72% (35/48),    6 kb
#> Receiving objects:  81% (39/48),    6 kb
#> Receiving objects:  91% (44/48),    6 kb
#> Receiving objects: 100% (48/48),    6 kb, done.

Make changes in README.md

status(repo)
#> Unstaged changes:
#>         Modified:   README.md
add(repo, "README.md")
commit(repo, "Another test with git2r")
push(repo, credentials = cred)
sessionInfo()
#> R version 3.2.0 (2015-04-16)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Ubuntu 14.04.2 LTS
#>
#> locale:
#>  [1] LC_CTYPE=sv_SE.UTF-8       LC_NUMERIC=C
#>  [3] LC_TIME=sv_SE.UTF-8        LC_COLLATE=sv_SE.UTF-8
#>  [5] LC_MONETARY=sv_SE.UTF-8    LC_MESSAGES=sv_SE.UTF-8
#>  [7] LC_PAPER=sv_SE.UTF-8       LC_NAME=C
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=sv_SE.UTF-8 LC_IDENTIFICATION=C
#>
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base
#>
#> other attached packages:
#> [1] git2r_0.10.1.9000
#>
#> loaded via a namespace (and not attached):
#> [1] compiler_3.2.0 tools_3.2.0

Hi @lcolladotor
I have made some more work on pushing to GitHub with git2r and I have successfully pushed over https with a GitHub PAT token, see #116

Thanks @stewid!

ssh with @git

Using the correct ssh key and @git remote works now for me as shown below. Using the incorrect ssh key leads to your new error message.

> library('git2r')
> cred <- cred_ssh_key('~/.ssh/id_rsa.pub', '~/.ssh/id_rsa')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...
Receiving objects:   2% (1/48),    6 kb
Receiving objects:  12% (6/48),    6 kb
Receiving objects:  22% (11/48),    6 kb
Receiving objects:  31% (15/48),    6 kb
Receiving objects:  41% (20/48),    6 kb
Receiving objects:  52% (25/48),    6 kb
Receiving objects:  62% (30/48),    6 kb
Receiving objects:  72% (35/48),    6 kb
Receiving objects:  81% (39/48),    6 kb
Receiving objects:  91% (44/48),    6 kb
Receiving objects: 100% (48/48),    6 kb, done.
> config(repo)

passwd with https

Also, using cred_user_pass() with a https remote also works for me:

> library('git2r')
> cred <- cred_user_pass('lcolladotor', 'MyPassword')
> repo <- clone("https://github.com/lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...
Receiving objects:   2% (1/48),    6 kb
Receiving objects:  12% (6/48),    6 kb
Receiving objects:  22% (11/48),    6 kb
Receiving objects:  31% (15/48),    6 kb
Receiving objects:  41% (20/48),    6 kb
Receiving objects:  52% (25/48),    6 kb
Receiving objects:  62% (30/48),    6 kb
Receiving objects:  72% (35/48),    6 kb
Receiving objects:  81% (39/48),    6 kb
Receiving objects:  91% (44/48),    6 kb
Receiving objects: 100% (48/48),    6 kb, done.

ssh with https

Also, using ssh key works for https remotes:

> library('git2r')
> cred <- cred_ssh_key('~/.ssh/id_rsa.pub', '~/.ssh/id_rsa')
> repo <- clone("https://github.com/lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...
Receiving objects:   2% (1/48),    6 kb
Receiving objects:  12% (6/48),    6 kb
Receiving objects:  22% (11/48),    6 kb
Receiving objects:  31% (15/48),    6 kb
Receiving objects:  41% (20/48),    6 kb
Receiving objects:  52% (25/48),    6 kb
Receiving objects:  62% (30/48),    6 kb
Receiving objects:  72% (35/48),    6 kb
Receiving objects:  81% (39/48),    6 kb
Receiving objects:  91% (44/48),    6 kb
Receiving objects: 100% (48/48),    6 kb, done.

passwd with @git

However, using cred_user_pass() does not work for git@ remote.

> library('git2r')
> cred <- cred_user_pass('lcolladotor', 'MyPassword')
> repo <- clone("git@github.com:lcolladotor/playground.git", "./playground", credentials = cred)
cloning into './playground'...
Error in clone("git@github.com:lcolladotor/playground.git", "./playground",  : 
  Error in 'git2r_clone': Unable to authenticate with supplied credentials

I'm not sure if that's intended. If not, then maybe using something like the following code chunk will help point users in the right direction. Specially because the message "Unable to authenticate with supplied credentials" first lead me to believe that I incorrectly typed my username or password.

## To be used inside clone()
##  Maybe at https://github.com/ropensci/git2r/blob/646f6ce82d108f41a018452b0566399b41354b20/R/repository.r#L326-L341
if(class(cred) == 'cred_user_pass' & grepl('git@github.com:', url)) {
    warning('Switching to https remote')
    url <- gsub('git@github.com:', 'https://github.com/', url)
}

## Maybe the code has to be more general
if(class(cred) == 'cred_user_pass' & grepl('git@', url)) {
    warning('Switching to https remote')
    url <- gsub('git@', 'https://', url)
    ## Substitute : for /
    ## Although it should probably only be the first one
    url <- gsub(':', '/', url)
}

Session info

> devtools::session_info()
Session info ------------------------------------------------------------------------------------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.2.0 Patched (2015-05-18 r68382)
 system   x86_64, darwin10.8.0                       
 ui       AQUA                                       
 language (EN)                                       
 collate  en_US.UTF-8                                
 tz       America/New_York                           

Packages ----------------------------------------------------------------------------------------------------------------------------------------------------------
 package   * version     date       source                         
 curl        0.9         2015-06-19 CRAN (R 3.2.1)                 
 devtools    1.8.0       2015-05-09 CRAN (R 3.2.0)                 
 digest      0.6.8       2014-12-31 CRAN (R 3.2.0)                 
 git2r     * 0.10.1.9000 2015-07-14 Github (ropensci/git2r@94831de)
 memoise     0.2.1       2014-04-22 CRAN (R 3.2.0)                 
 Rcpp        0.11.6      2015-05-01 CRAN (R 3.2.0)                 
 rversions   1.0.1       2015-06-06 CRAN (R 3.2.0)                 
 xml2        0.1.1       2015-06-02 CRAN (R 3.2.0)          

This message is more for my own use than for the issue at hand.


Regarding my original use case. 2 of the 3 pull() calls work using a git@ remote with cred_ssh_key() credentials.

Works:

push(repo, 'origin', 'refs/heads/gh-pages', credentials = cred)
push(repo, 'origin', "refs/heads/gh-pages:refs/heads/gh-pages", credentials = cred)

Doesn't work:

> push(repo, 'origin', 'gh-pages', credentials = cred)
Error in .local(object, ...) : 
  Error in 'git2r_push': Unable to authenticate with supplied credentials

I was expecting this to work given the command git push -u origin gh-pages works. But in particular the first case that works follows the syntax shown in the push() examples. So users should be able to find that syntax without much problem.

Full code

## Initiate repo
path <- '/Users/lcollado/Dropbox/Github/testgit2r'
dir.create(path)
library('git2r')
repo <- init(path)
remote_add(repo, 'origin', 'git@github.com:lcolladotor/testgit2r.git')

## Add file and switch to gh-pages branch
writeLines("Hello world!!", file.path(path, "example.txt"))
add(repo, "example.txt")
ci <- commit(repo, "Commit message")
checkout(repo, branch = 'gh-pages', create = TRUE)

## 3 different ways to try to push, taken from docs and other issues
cred <- cred_ssh_key('~/.ssh/id_rsa.pub', '~/.ssh/id_rsa')
push(repo, 'origin', 'refs/heads/gh-pages', credentials = cred)
## Delete https://github.com/lcolladotor/testgit2r and re-make it so it's clean
push(repo, 'origin', 'gh-pages', credentials = cred)
## No need to reset https://github.com/lcolladotor/testgit2r at this point since the above
## command fails
push(repo, 'origin', "refs/heads/gh-pages:refs/heads/gh-pages", credentials = cred)

Session info

> devtools::session_info()
Session info ------------------------------------------------------------------------------------------------------------------------------------------------------
 setting  value                                      
 version  R version 3.2.0 Patched (2015-05-18 r68382)
 system   x86_64, darwin10.8.0                       
 ui       AQUA                                       
 language (EN)                                       
 collate  en_US.UTF-8                                
 tz       America/New_York                           

Packages ----------------------------------------------------------------------------------------------------------------------------------------------------------
 package   * version     date       source                         
 curl        0.9         2015-06-19 CRAN (R 3.2.1)                 
 devtools    1.8.0       2015-05-09 CRAN (R 3.2.0)                 
 digest      0.6.8       2014-12-31 CRAN (R 3.2.0)                 
 git2r     * 0.10.1.9000 2015-07-14 Github (ropensci/git2r@94831de)
 memoise     0.2.1       2014-04-22 CRAN (R 3.2.0)                 
 Rcpp        0.11.6      2015-05-01 CRAN (R 3.2.0)                 
 rversions   1.0.1       2015-06-06 CRAN (R 3.2.0)                 
 xml2        0.1.1       2015-06-02 CRAN (R 3.2.0)