c# - 如何使用 GitHub DB API 提交对文件的更改

标签 c# .net git github github-api

我正在尝试使用 C# 使用 GitHub DB API 更新文件。此处定义了执行此操作的过程 http://developer.github.com/v3/git/如下

  • 获取当前提交对象
  • 检索它指向的树
  • 检索树针对特定文件路径的 blob 对象的内容
  • 以某种方式更改内容并发布一个包含该新内容的新 blob 对象,获取 blob SHA 返回
  • 发布一个新的树对象,该文件路径指针替换为您的新 blob SHA * 返回一个树 SHA
  • 创建一个新的提交对象,以当前提交的 SHA 作为父对象和新的树 SHA,获取提交的 SHA 回来
  • 更新分支的引用以指向新的提交 SHA

然而,当我到达点时它失败了

update the reference of your branch to point to the new commit SHA

即线

var updateReferenceResponse = Patch<UpdateReferenceResponse>("git/refs/heads/master", updateReferenceRequest);

响应失败

<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>

这是我尝试调用的特定 API http://developer.github.com/v3/git/refs/#update-a-reference

下面是代码的主要工作原理

[Test]
public void UpdateFileUsingGithubDataApi()
{
    var branch = GetUrlResponse<BranchResponse>("branches/master");
    var currentCommitSha = branch.commit.sha;

    var tree = GetUrlResponse<CommitResponse>("git/commits/" + currentCommitSha).tree;
    var createBlob = new CreateBlobRequest
                     {
                         content = "sdkfn",
                         encoding = "utf-8"
                     };
    var blobResponse = Post<CreateBlobResponse>("git/blobs", createBlob);
    var blobSha = blobResponse.sha;
    var createTreeRequest = new CreateTreeRequest
                            {
                                base_tree = tree.sha,
                                tree = new List<CreateTreeRequest.Tree>
                                       {
                                           new CreateTreeRequest.Tree
                                           {
                                               path = "README.md",
                                               mode = "100644",
                                               type = "blob",
                                               sha = blobSha
                                           }
                                       }
                            };

    var treeResponse = Post<CreateTreeResponse>("git/trees", createTreeRequest);

    var createCommitRequest = new CreateCommitRequest
                              {
                                  parent = new List<string>
                                           {
                                               currentCommitSha
                                           },
                                  message = "foo",
                                  tree = treeResponse.sha
                              };
    var commitResponse = Post<CreateCommitResponse>("git/commits", createCommitRequest);

    var updateReferenceRequest = new UpdateReferenceRequest
                                 {
                                     sha = commitResponse.sha
                                 };
    var updateReferenceResponse = Patch<UpdateReferenceResponse>("git/refs/heads/master", updateReferenceRequest);
}

TResponse Post<TResponse>(string suffix, object value)
{
    return Send<TResponse>(suffix, value, "Post");
}


TResponse Patch<TResponse>(string suffix, object value)
{
    return Send<TResponse>(suffix, value, "Patch");
}

TResponse Send<TResponse>(string suffix, object value, string method)
{
    var serializeObject = JsonConvert.SerializeObject(value, Formatting.Indented);
    var sourceUrl = string.Format("https://api.github.com/repos/{0}/{1}/{2}", UserName, repo, suffix);
    Debug.WriteLine("\r\n{0}ing to {1} with data\r\n{2}", method, sourceUrl, serializeObject);
    var webRequest = WebRequest.Create(sourceUrl);
    webRequest.Method = method;
    AddAuth(webRequest);
    var requestStream = webRequest.GetRequestStream();
    using (var streamWriter = new StreamWriter(requestStream))
    {
        streamWriter.Write(serializeObject);
    }
    try
    {
        using (var webResponse = webRequest.GetResponse())
        {
            var text = webResponse.GetResponseStream().ReadToEnd();

            Debug.WriteLine("response:\r\n" + text.GetPrettyPrintedJson());
            return JsonConvert.DeserializeObject<TResponse>(text);
        }
    }
    catch (WebException exception)
    {
        var readToEnd = exception.Response.GetResponseStream().ReadToEnd();
        Debug.WriteLine("failed with response:\r\n" + readToEnd);
        throw new Exception(readToEnd);
    }
}

TResponse GetUrlResponse<TResponse>(string suffix)
{
    var sourceUrl = string.Format("https://api.github.com/repos/{0}/{1}/{2}", UserName, repo, suffix);
    var webRequest = WebRequest.Create(sourceUrl);
    Debug.WriteLine("\r\nrequesting " + sourceUrl);
    AddAuth(webRequest);
    using (var webResponse = webRequest.GetResponse())
    {
        var text = webResponse.GetResponseStream().ReadToEnd();
        Debug.WriteLine("response:\r\n"+ text.GetPrettyPrintedJson());
        return JsonConvert.DeserializeObject<TResponse>(text);
    }
}

void AddAuth(WebRequest webRequest)
{
    if (UserName != null && Password != null)
    {
        var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", UserName, Password)));
        webRequest.Headers.Add("Authorization", string.Format("Basic {0}", token));
    }
}

这是http对话的抄本

requesting https://api.github.com/repos/simoncropp/test/branches/master
response:
{
  "name": "master",
  "commit": {
    "sha": "a4447748c9cd36601127e3a6143348a1695cc2e8",
    "commit": {
      "message": "Initial commit",
      "tree": {
        "sha": "5b3438cf3aca03901bdb2ae1722bc7e05738a7fe",
      },
      "comment_count": 0
    },
  },
}

requesting https://api.github.com/repos/simoncropp/test/git/commits/a4447748c9cd36601127e3a6143348a1695cc2e8
response:
{
  "sha": "a4447748c9cd36601127e3a6143348a1695cc2e8",
  "tree": {
    "sha": "5b3438cf3aca03901bdb2ae1722bc7e05738a7fe",
  },
  "message": "Initial commit",
  "parents": []
}

Posting to https://api.github.com/repos/simoncropp/test/git/blobs with data
{
  "content": "sdkfn",
  "encoding": "utf-8"
}
response:
{
  "sha": "2b664114096f7ff36664e381c5fbd0030f47009c",
}

Posting to https://api.github.com/repos/simoncropp/test/git/trees with data
{
  "base_tree": "5b3438cf3aca03901bdb2ae1722bc7e05738a7fe",
  "tree": [
    {
      "path": "README.md",
      "mode": "100644",
      "type": "blob",
      "sha": "2b664114096f7ff36664e381c5fbd0030f47009c"
    }
  ]
}
response:
{
  "sha": "fd1379d51016989a615acf79409256849dc8ea7f",
  "tree": [
    {
      "mode": "100644",
      "type": "blob",
      "sha": "bdc3535f745bc86966fb24c67d252c3ea68e8e03",
      "path": ".gitignore",
      "size": 1522,
    },
    {
      "mode": "100644",
      "type": "blob",
      "sha": "e0369aaa94e2bc8dce560c0ae0669d74204602d5",
      "path": "LICENSE",
      "size": 1078,
    },
    {
      "mode": "100644",
      "type": "blob",
      "sha": "2b664114096f7ff36664e381c5fbd0030f47009c",
      "path": "README.md",
      "size": 5,
    }
  ]
}

Posting to https://api.github.com/repos/simoncropp/test/git/commits with data
{
  "message": "foo",
  "tree": "fd1379d51016989a615acf79409256849dc8ea7f",
  "parent": [
    "a4447748c9cd36601127e3a6143348a1695cc2e8"
  ]
}
response:
{
  "sha": "f66832493d22c58a6dd9d41b65504c1e9c901d7a",
  "tree": {
    "sha": "fd1379d51016989a615acf79409256849dc8ea7f",
  },
  "message": "foo",
  "parents": []
}

Patching to https://api.github.com/repos/simoncropp/test/git/refs/heads/master with data
{
  "sha": "f66832493d22c58a6dd9d41b65504c1e9c901d7a"
}
failed with response:
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>

最佳答案

Posting to https://api.github.com/repos/simoncropp/test/git/commits with data
{
  "message": "foo",
  "tree": "fd1379d51016989a615acf79409256849dc8ea7f",
  "parent": [
    "a4447748c9cd36601127e3a6143348a1695cc2e8"
  ]
}

文档在这里需要一个 parents 参数,而不是 parent

response:
{
  "sha": "f66832493d22c58a6dd9d41b65504c1e9c901d7a",
  "tree": {
    "sha": "fd1379d51016989a615acf79409256849dc8ea7f",
  },
  "message": "foo",
  "parents": []
}

没有它,你会得到一个空的父提交数组,坏事就会发生。

关于c# - 如何使用 GitHub DB API 提交对文件的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19284910/

相关文章:

c# - 带有程序集引用的 asp.net 3.5 引用项目在单元测试中抛出签名/强名称错误

c# - 使用 GIT 进行软件版本控制

jquery - 使用 JQuery 单击 RadioButtonList 隐藏面板

C#引用分配未按预期工作

git - 如何在给定 pull 号时应用 git 补丁

git - 如何使我的分支与其对应的远程分支相同?

c# - Exchange/Outlook 2010,C# SenderEmailAddress 附加到名称的额外字符

c# - sql server 从表中选择百分比并从另一个表中选择所有数据

c# - 如何在 asp.net c# 中以 pdf 格式导出 syncfusion 图表

c# - C#获取7.1音频中每个扬声器的音频音量