在Windows上使用R将本地代码库推送到GitHub

15
我曾经提出过一个非常 相似的问题,得到了一条从命令行起作用的响应,但现在我想使用R来自动化Windows上的这个过程(Linux要容易得多)。
以下是我正在尝试做的事情:
  1. 创建本地目录(如果已存在则忽略)
  2. 根据本地目录的名称,在云端生成一个新的github repo(基于此答案
  3. 将.git添加到本地repo中
  4. 进行初始提交
  5. 建立云repo和本地repo之间的链接
  6. 将提交和本地repo中的文件推送到github
我相信根据输出的结果在失败之前我已经完成了第5步(因为提交和本地目录中的文件从未上传到云端github)。我知道第2步有效,因为空仓库是在这里创建的。我不知道如何测试第5步。在最后一步shell(cmd6, intern = T)时,RGui和RStudio会进入永久的死循环。问题是:如何将提交和本地仓库推送到云端。

这是我的更新代码(唯一特定于用户的是第三个代码块中的用户名和密码):

## Create Directory
repo <- "foo5"
dir.create(repo)
project.dir <- file.path(getwd(), repo) 

## Throw a READ.ME in the directory
cat("This is a test", file=file.path(project.dir, "READ.ME"))

## Github info (this will change per user)
password <-"pass" 
github.user <- "trinker"  

## Get git location
test <- c(file.exists("C:/Program Files (x86)/Git/bin/git.exe"),
    file.exists("C:/Program Files/Git/bin/git.exe"))
gitpath <- c("C:/Program Files (x86)/Git/bin/git.exe",
  "C:/Program Files/Git/bin/git.exe")[test][1]

## download curl and set up github api
wincurl <- "http://curl.askapache.com/download/curl-7.32.0-win64-ssl-sspi.zip"
url <- wincurl
tmp <- tempfile( fileext = ".zip" )
download.file(url,tmp)
unzip(tmp, exdir = tempdir())       
shell(paste0(tempdir(), "/curl http://curl.haxx.se/ca/cacert.pem -o " , 
    tempdir() , "/curl-ca-bundle.crt"))
json <- paste0(" { \"name\":\"" , repo , "\" } ") #string we desire formatting
json <- shQuote(json , type = "cmd" )
cmd1 <- paste0( tempdir() ,"/curl -i -u \"" , github.user , ":" , password , 
    "\" https://api.github.com/user/repos -d " , json )

shell(cmd1, intern = T)

## Change working directory
wd <- getwd()
setwd(project.dir)

## set up the .git directory
cmd2 <- paste0(shQuote(gitpath), " init")
shell(cmd2, intern = T)

## add all the contents of the directory for tracking
cmd3 <- paste0(shQuote(gitpath), " add .")  
shell(cmd3, intern = T)       

cmdStat <- paste0(shQuote(gitpath), " status")  
shell(cmdStat, intern = T)

## Set email (may not be needed)
Trim <- function (x) gsub("^\\s+|\\s+$", "", x) #remove trailing/leading white 

x <- file.path(path.expand("~"), ".gitconfig")
if (file.exists(x)) {
    y <- readLines(x)
    email <- Trim(unlist(strsplit(y[grepl("email = ", y)], "email ="))[2])
} else {
    z <- file.path(Sys.getenv("HOME"), ".gitconfig")
    if (file.exists(z)) {
        email <- Trim(unlist(strsplit(y[grepl("email = ", y)], "email ="))[2])
    } else {
        warning(paste("Set `email` in", x))
    }
}
cmdEM <- paste0(shQuote(gitpath), sprintf(" config --global user.email %s", email))        
system(cmdEM, intern = T)

## Initial commit
cmd4 <- paste0(shQuote(gitpath), ' commit -m "Initial commit"')  
system(cmd4, intern = T) 

## establish connection between local and remote
cmd5 <- paste0(shQuote(gitpath), " remote add origin https://github.com/",
    github.user, "/", repo, ".git")  
shell(cmd5, intern = T) 

## push local to remote 
cmd6 <- paste0(shQuote(gitpath), " push -u origin master")  
shell(cmd6, intern = T) 

setwd(wd)

我知道这个脚本有点长,但为了重新创建问题并复制问题,所有内容都是必要的:
注意:在Simon的回答下,我更新了问题,因为他是正确的,并且更接近推动。原始问题的内容可以在这里找到。

仓库看起来没问题吗?可能是Windows锁定文件并不释放的问题。另外,尝试将cmd3更改为paste0(shQuote(gitpath), " add -all"),然后立即运行paste0(shQuote(gitpath), " status")而且你可能需要添加一个开关来确定平台,如果在Windows上使用shell而不是system。我发现shellWindows上更加友好。 - Simon O'Hanlon
根据我的经验,几乎总是更好地使用“system”而不是“shell”。 - hadley
2个回答

8
如果您正在使用https地址,请确保:
  • 环境变量%HOME%已定义
  • 其中存在一个_netrc文件,并具有正确的凭据以将更改推回到您的存储库

该文件应包含以下内容:

machine github.com
login username
password xxxx
protocol https

即使您在GitHub上激活了最近的两步验证,这也适用于您的操作。然后您的推送不会超时。
cmd6 <- paste0(shQuote(gitpath), " push -u origin master")  
shell(cmd6, intern = T) 

这比 设置公共/私有 SSH 密钥 更简单。
作为OP Tyler Rinker评论的,设置%HOME%的方法在我的另一个回答 "Git - How to use .netrc file on windows to save user and password" 中有说明。
这通常是通过git-cmd.bat来完成的:
if not exist "%HOME%" @set HOME=%HOMEDRIVE%%HOMEPATH%
@if not exist "%HOME%" @set HOME=%USERPROFILE%

但您也可以手动完成它。

我不是最懂计算机的人。你能稍微解释一下什么是“定义了环境变量%HOME%”吗?这是否意味着Sys.getenv()["HOME"] - Tyler Rinker
我看到了这篇相关的帖子:https://dev59.com/i2025IYBdhLWcg3wZlHd - Tyler Rinker
@TylerRinker 对不起回复晚了:你的评论是正确的,只是我当时正在夜间。 - VonC

2
这个问题似乎仅仅是混淆了sshhttps协议。
请注意,URL应该为:
#  https:
"https://github.com/<username>/<myrepo>.git"

#  ssh:
"git@github.com:<username>/<repo>.git"

你有:

cmd5 <- paste0(shQuote(gitpath), " remote add origin https://github.com:",
github.user, "/", repo, ".git") 
cat( cmd5 )
"... remote add origin https://github.com:trinker/foo2.git"

只需将 cmd5 更改为
# Note the forward slash at EOL in place of the colon
cmd5 <- paste0(shQuote(gitpath), " remote add origin https://github.com/",
github.user, "/", repo, ".git")
"... remote add origin https://github.com/trinker/foo2.git"

在执行git add .之后立即运行这个命令也不会有任何坏处:

cmdStat <- paste0(shQuote(gitpath), " status")  
shell(cmdStat, intern = T)

Simon,你说得对。这让我跨过了下一个障碍。最后一步是push -u origin master。这会导致RGui和RStudio陷入死循环。我看到你在github上创建了一个foo repo,但现在已经不存在了。你成功地推送了吗?如果是的话,你有什么想法,我做错了什么吗?由于它是一个死循环,所以我没有错误消息。我更新了上面的代码/问题,以显示我做了什么。 - Tyler Rinker
@TylerRinker 嗯,我也遇到了死循环。我想 git 只是超时了。这可能是非常明显的问题,我们只是没有注意到!下班后我会戴上我的思考帽子(谁会在工作时思考):-) - Simon O'Hanlon
我在想,RStudio中的“push”操作需要我的用户名和密码。这可能意味着API在这里也是必需的(这只是我提出的一个想法,但我还不完全理解API的工作原理)。 - Tyler Rinker
我开始使用 json2 <- " { \"events\":\"push\" } ",并重复你对cmd1所做的操作,但由于我没有指定仓库,它失败了,但这种格式非常棘手。 - Tyler Rinker
是的,我认为这是在尝试通过http推送时遇到的问题。我们应该尝试使用ssh来解决... - Simon O'Hanlon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接