-
Notifications
You must be signed in to change notification settings - Fork 362
Translate B-embedding-git libgit2 #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
30cf1a1
fa79274
5341427
9a7aeaf
832c5ff
dbbd539
e9818a9
8dcb33e
2e1b736
1f25fbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,60 @@ | ||
=== Libgit2 | ||
|
||
(((libgit2)))(((C))) | ||
Another option at your disposal is to use Libgit2. | ||
Libgit2 is a dependency-free implementation of Git, with a focus on having a nice API for use within other programs. | ||
You can find it at http://libgit2.github.com[]. | ||
另外一种可以供你使用的是 Libgit2。 | ||
Libgit2 是一个 Git 的非依赖性的工具,它致力于为其他程序使用 Git 提供更好的 API。 | ||
你可以在 http://libgit2.github.com[] 找到它。 | ||
|
||
First, let's take a look at what the C API looks like. | ||
Here's a whirlwind tour: | ||
首先,让我们来看一下 C API 长啥样。 | ||
这是一个旋风式旅行。 | ||
|
||
[source,c] | ||
----- | ||
// Open a repository | ||
// 打开一个版本库 | ||
git_repository *repo; | ||
int error = git_repository_open(&repo, "/path/to/repository"); | ||
|
||
// Dereference HEAD to a commit | ||
// 逆向引用 HEAD 到一个提交 | ||
git_object *head_commit; | ||
error = git_revparse_single(&head_commit, repo, "HEAD^{commit}"); | ||
git_commit *commit = (git_commit*)head_commit; | ||
|
||
// Print some of the commit's properties | ||
// 显示这个提交的一些详情 | ||
printf("%s", git_commit_message(commit)); | ||
const git_signature *author = git_commit_author(commit); | ||
printf("%s <%s>\n", author->name, author->email); | ||
const git_oid *tree_id = git_commit_tree_id(commit); | ||
|
||
// Cleanup | ||
// 清理现场 | ||
git_commit_free(commit); | ||
git_repository_free(repo); | ||
----- | ||
|
||
The first couple of lines open a Git repository. | ||
The `git_repository` type represents a handle to a repository with a cache in memory. | ||
This is the simplest method, for when you know the exact path to a repository's working directory or `.git` folder. | ||
There's also the `git_repository_open_ext` which includes options for searching, `git_clone` and friends for making a local clone of a remote repository, and `git_repository_init` for creating an entirely new repository. | ||
前两行打开一个 Git 版本库。 | ||
这个 `git_repository` 类型代表了一个在内存中带有缓存的指向一个版本库的句柄。 | ||
这是最简单的方法,只是你必须知道一个版本库的工作目录或者一个 `.git` 文件夹的精确路径。 | ||
另外还有 `git_repository_open_ext` ,它包括了带选项的搜索, `git_clone` 及其同类可以用来做远程版本库的本地克隆, `git_repository_init` 则可以创建一个全新的版本库。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 另外还有 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @IceNature 和它?它指代的是?其实我也不太明白那个 friends 代表啥。。。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. git clone…… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @IceNature 所以 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是的 |
||
|
||
The second chunk of code uses rev-parse syntax (see <<_branch_references>> for more on this) to get the commit that HEAD eventually points to. | ||
The type returned is a `git_object` pointer, which represents something that exists in the Git object database for a repository. | ||
`git_object` is actually a ``parent'' type for several different kinds of objects; the memory layout for each of the ``child'' types is the same as for `git_object`, so you can safely cast to the right one. | ||
In this case, `git_object_type(commit)` would return `GIT_OBJ_COMMIT`, so it's safe to cast to a `git_commit` pointer. | ||
第二段代码使用了一种 rev-parse 语法(要了解更多,请看 <<_branch_references>> )来得到 HEAD 真正指向的提交。 | ||
返回类型是一个 `git_object` 指针,它指代位于版本库里的 Git 对象数据库中的某个东西。 | ||
`git_object` 实际上是几种不同的对象的 ``父'' 类型,每个 ``子'' 类型的内存布局和 `git_object` 是一样的,所以你能安全地把它们转换为正确的类型。 | ||
在上面的例子中, `git_object_type(commit)` 会返回 `GIT_OBJ_COMMIT` ,所以转换成 `git_commit` 指针是安全的。 | ||
|
||
The next chunk shows how to access the commit's properties. | ||
The last line here uses a `git_oid` type; this is Libgit2's representation for a SHA-1 hash. | ||
下一段展示了如何访问一个提交的详情。 | ||
最后一行使用了 `git_oid` 类型,这是 Libgit2 用来表示一个 SHA-1 哈希的方法。 | ||
|
||
From this sample, a couple of patterns have started to emerge: | ||
从这个例子中,我们可以看到一些模式: | ||
|
||
* If you declare a pointer and pass a reference to it into a Libgit2 call, that call will probably return an integer error code. | ||
A `0` value indicates success; anything less is an error. | ||
* If Libgit2 populates a pointer for you, you're responsible for freeing it. | ||
* If Libgit2 returns a `const` pointer from a call, you don't have to free it, but it will become invalid when the object it belongs to is freed. | ||
* Writing C is a bit painful. | ||
* 如果你声明了一个指针,并在一个 Libgit2 调用中传递一个引用,那么这个调用可能返回一个 int 类型的错误码。 | ||
值 `0` 表示成功,比它小的则是一个错误。 | ||
* 如果 Libgit2 为你填入一个指针,那么你有责任释放它。 | ||
* 如果 Libgit2 在一个调用中返回一个 `const` 指针,你不需要释放它,但是当它所指向的对象被释放时它将不可用。 | ||
* 用 C 来写有点蛋疼。 | ||
|
||
(((Ruby))) | ||
That last one means it isn't very probable that you'll be writing C when using Libgit2. | ||
Fortunately, there are a number of language-specific bindings available that make it fairly easy to work with Git repositories from your specific language and environment. | ||
Let's take a look at the above example written using the Ruby bindings for Libgit2, which are named Rugged, and can be found at https://github.com/libgit2/rugged[]. | ||
最后一点意味着你应该不会在使用 Libgit2 时编写 C 语言程序。 | ||
但幸运的是,有许多可用的各种语言的绑定,能让你在特定的语言和环境中更加容易的操作 Git 版本库。 | ||
我们来看一下下面这个用 Libgit2 的 Ruby 绑定写成的例子,它叫 Rugged,你可以在 https://github.com/libgit2/rugged[] 找到它。 | ||
|
||
[source,ruby] | ||
---- | ||
|
@@ -65,10 +65,10 @@ puts "#{commit.author[:name]} <#{commit.author[:email]}>" | |
tree = commit.tree | ||
---- | ||
|
||
As you can see, the code is much less cluttered. | ||
Firstly, Rugged uses exceptions; it can raise things like `ConfigError` or `ObjectError` to signal error conditions. | ||
Secondly, there's no explicit freeing of resources, since Ruby is garbage-collected. | ||
Let's take a look at a slightly more complicated example: crafting a commit from scratch | ||
你可以发现,代码看起来更加清晰了。 | ||
首先, Rugged 使用异常机制,它可以抛出类似于 `ConfigError` 或者 `ObjectError` 之类的东西来告知错误的情况。 | ||
其次,不需要明确资源释放,因为 Ruby 是支持垃圾回收的。 | ||
我们来看一个稍微复杂一点的例子:从头开始制作一个提交。 | ||
|
||
[source,ruby] | ||
---- | ||
|
@@ -95,29 +95,29 @@ commit_id = Rugged::Commit.create(repo, | |
commit = repo.lookup(commit_id) # <8> | ||
---- | ||
|
||
<1> Create a new blob, which contains the contents of a new file. | ||
<2> Populate the index with the head commit's tree, and add the new file at the path `newfile.txt`. | ||
<3> This creates a new tree in the ODB, and uses it for the new commit. | ||
<4> We use the same signature for both the author and committer fields. | ||
<5> The commit message. | ||
<6> When creating a commit, you have to specify the new commit's parents. | ||
This uses the tip of HEAD for the single parent. | ||
<7> Rugged (and Libgit2) can optionally update a reference when making a commit. | ||
<8> The return value is the SHA-1 hash of a new commit object, which you can then use to get a `Commit` object. | ||
<1> 创建一个新的 blob ,它包含了一个新文件的内容。 | ||
<2> 将 HEAD 提交树填入索引,并在路径 `newfile.txt` 增加新文件。 | ||
<3> 这就在 ODB 中创建了一个新的树,并在一个新的提交中使用它。 | ||
<4> 我们在 author 栏和 committer 栏使用相同的签名。 | ||
<5> 提交的信息。 | ||
<6> 当创建一个提交时,你必须指定这个新提交的父提交。 | ||
这里使用了 HEAD 的末尾作为单一的父提交。 | ||
<7> 在做一个提交的过程中, Rugged (和 Libgit2 )能在需要时更新引用。 | ||
<8> 返回值是一个新提交对象的 SHA-1 哈希,你可以用它来获得一个 `Commit` 对象。 | ||
|
||
The Ruby code is nice and clean, but since Libgit2 is doing the heavy lifting, this code will run pretty fast, too. | ||
If you're not a rubyist, we touch on some other bindings in <<_libgit2_bindings>>. | ||
Ruby 的代码很好很简洁,另一方面因为 Libgit2 做了大量工作,所以代码运行起来其实速度也不赖。 | ||
如果你不是一个 Ruby 程序员,我们在 <<_libgit2_bindings>> 有提到其它的一些绑定。 | ||
|
||
|
||
==== Advanced Functionality | ||
==== 高级功能 | ||
|
||
Libgit2 has a couple of capabilities that are outside the scope of core Git. | ||
One example is pluggability: Libgit2 allows you to provide custom ``backends'' for several types of operation, so you can store things in a different way than stock Git does. | ||
Libgit2 allows custom backends for configuration, ref storage, and the object database, among other things. | ||
Libgit2 有几个超过核心 Git 的能力。 | ||
例如它的可定制性:Libgit2 允许你为一些不同类型的操作自定义的``后端'',让你得以使用与原生 Git 不同的方式存储东西。 | ||
Libgit2 允许为自定义后端指定配置、引用的存储以及对象数据库, | ||
|
||
Let's take a look at how this works. | ||
The code below is borrowed from the set of backend examples provided by the Libgit2 team (which can be found at https://github.com/libgit2/libgit2-backends[]). | ||
Here's how a custom backend for the object database is set up: | ||
我们来看一下它究竟是怎么工作的。 | ||
下面的例子借用自 Libgit2 团队提供的后端样本集 (可以在 https://github.com/libgit2/libgit2-backends[] 上找到)。 | ||
一个对象数据库的自定义后端是这样建立的: | ||
|
||
[source,c] | ||
---- | ||
|
@@ -134,23 +134,23 @@ error = git_repository_open(&repo, "some-path"); | |
error = git_repository_set_odb(odb); // <4> | ||
---- | ||
|
||
_(Note that errors are captured, but not handled. We hope your code is better than ours.)_ | ||
_(注意:这个错误被捕获了,但是没有被处理。我们希望你的代码比我们的更好。)_ | ||
|
||
<1> Initialize an empty object database (ODB) ``frontend,'' which will act as a container for the ``backends'' which are the ones doing the real work. | ||
<2> Initialize a custom ODB backend. | ||
<3> Add the backend to the frontend. | ||
<4> Open a repository, and set it to use our ODB to look up objects. | ||
<1> 初始化一个空的对象数据库( ODB ) ``前端'',它将被作为一个用来做真正的工作的 ``后端'' 的容器。 | ||
<2> 初始化一个自定义 ODB 后端。 | ||
<3> 为这个前端增加一个后端。 | ||
<4> 打开一个版本库,并让它使用我们的 ODB 来寻找对象。 | ||
|
||
But what is this `git_odb_backend_mine` thing? | ||
Well, that's the constructor for your own ODB implementation, and you can do whatever you want in there, so long as you fill in the `git_odb_backend` structure properly. | ||
Here's what it _could_ look like: | ||
但是 `git_odb_backend_mine` 是个什么东西呢? | ||
嗯,那是一个你自己的 ODB 实现的构造器,并且你能在那里做任何你想做的事,前提是你能正确地填写 `git_odb_backend` 结构。 | ||
它看起来_应该_是这样的: | ||
|
||
[source,c] | ||
---- | ||
typedef struct { | ||
git_odb_backend parent; | ||
|
||
// Some other stuff | ||
// 其它的一些东西 | ||
void *custom_context; | ||
} my_backend_struct; | ||
|
||
|
@@ -165,49 +165,49 @@ int git_odb_backend_mine(git_odb_backend **backend_out, /*…*/) | |
backend->parent.read = &my_backend__read; | ||
backend->parent.read_prefix = &my_backend__read_prefix; | ||
backend->parent.read_header = &my_backend__read_header; | ||
// … | ||
// …… | ||
|
||
*backend_out = (git_odb_backend *) backend; | ||
|
||
return GIT_SUCCESS; | ||
} | ||
---- | ||
|
||
The subtlest constraint here is that `my_backend_struct`'s first member must be a `git_odb_backend` structure; this ensures that the memory layout is what the Libgit2 code expects it to be. | ||
The rest of it is arbitrary; this structure can be as large or small as you need it to be. | ||
`my_backend_struct` 的第一个成员必须是一个 `git_odb_backend` 结构,这是一个微妙的限制:这样就能确保内存布局是 Libgit2 的代码所期望的样子。 | ||
其余都是随意的,这个结构的大小可以随心所欲。 | ||
|
||
The initialization function allocates some memory for the structure, sets up the custom context, and then fills in the members of the `parent` structure that it supports. | ||
Take a look at the `include/git2/sys/odb_backend.h` file in the Libgit2 source for a complete set of call signatures; your particular use case will help determine which of these you'll want to support. | ||
这个初始化函数为该结构分配内存,设置自定义的上下文,然后填写它支持的 `parent` 结构的成员。 | ||
阅读 Libgit2 的 `include/git2/sys/odb_backend.h` 源码以了解全部调用签名,你特定的使用环境会帮你决定使用哪一种调用签名。 | ||
|
||
[[_libgit2_bindings]] | ||
==== Other Bindings | ||
==== 其它绑定 | ||
|
||
Libgit2 has bindings for many languages. | ||
Here we show a small example using a few of the more complete bindings pakages as of this writing; libraries exist for many other languages, including C++, Go, Node.js, Erlang, and the JVM, all in various stages of maturity. | ||
The official collection of bindings can be found by browsing the repositories at https://github.com/libgit2[]. | ||
The code we'll write will return the commit message from the commit eventually pointed to by HEAD (sort of like `git log -1`). | ||
Libgit2 有很多种语言的绑定。 | ||
在这篇文章中,我们展现了一个使用了几个更加完整的绑定包的小例子,这些库存在于许多种语言中,包括 C++、Go、Node.js、Erlang 以及 JVM ,它们的成熟度各不相同。 | ||
官方的绑定集合可以通过浏览这个版本库得到:https://github.com/libgit2[] 。 | ||
我们写的代码将返回当前 HEAD 指向的提交的提交信息(就像 `git log -1` 那样)。 | ||
|
||
|
||
===== LibGit2Sharp | ||
|
||
(((.NET)))(((C#)))(((Mono))) | ||
If you're writing a .NET or Mono application, LibGit2Sharp (https://github.com/libgit2/libgit2sharp[]) is what you're looking for. | ||
The bindings are written in C#, and great care has been taken to wrap the raw Libgit2 calls with native-feeling CLR APIs. | ||
Here's what our example program looks like: | ||
如果你在编写一个 .NET 或者 Mono 应用,那么 LibGit2Sharp (https://github.com/libgit2/libgit2sharp[]) 就是你所需要的。 | ||
这个绑定是用 C# 写成的,并且已经采取许多措施来用令人感到自然的 CLR API 包装原始的 Libgit2 的调用。 | ||
我们的例子看起来就像这样: | ||
|
||
[source,csharp] | ||
----- | ||
new Repository(@"C:\path\to\repo").Head.Tip.Message; | ||
----- | ||
|
||
For desktop Windows applications, there's even a NuGet package that will help you get started quickly. | ||
对于 Windows 桌面应用,一个叫做 NuGet 的包会让你快速上手。 | ||
|
||
===== objective-git | ||
|
||
(((Apple)))(((Objective-C)))(((Cocoa))) | ||
If your application is running on an Apple platform, you're likely using Objective-C as your implementation language. | ||
Objective-Git (https://github.com/libgit2/objective-git[]) is the name of the Libgit2 bindings for that environment. | ||
The example program looks like this: | ||
如果你的应用运行在一个 Apple 平台上,你很有可能使用 Objective-C 作为实现语言。 | ||
Objective-Git (https://github.com/libgit2/objective-git[]) 是这个环境下的 Libgit2 绑定。 | ||
一个例子看起来类似这样: | ||
|
||
[source,objc] | ||
----- | ||
|
@@ -216,25 +216,25 @@ GTRepository *repo = | |
NSString *msg = [[[repo headReferenceWithError:NULL] resolvedTarget] message]; | ||
----- | ||
|
||
Objective-git is fully interoperable with Swift, so don't fear if you've left Objective-C behind. | ||
Objective-git 与 Swift 完美兼容,所以你把 Objective-C 落在一边的时候不用恐惧。 | ||
|
||
|
||
===== pygit2 | ||
|
||
(((Python))) | ||
The bindings for Libgit2 in Python are called Pygit2, and can be found at http://www.pygit2.org/[]. | ||
Our example program: | ||
Python 的 Libgit2 绑定叫做 Pygit2 ,你可以在 http://www.pygit2.org/[] 找到它。 | ||
我们的示例程序: | ||
|
||
[source,python] | ||
---- | ||
pygit2.Repository("/path/to/repo") # open repository | ||
.head.resolve() # get a direct ref | ||
.get_object().message # get commit, read message | ||
pygit2.Repository("/path/to/repo") # 打开版本库 | ||
.head.resolve() # 获取直接引用 | ||
.get_object().message # 获取提交,读取信息。 | ||
---- | ||
|
||
|
||
==== Further Reading | ||
==== 扩展阅读 | ||
|
||
Of course, a full treatment of Libgit2's capabilities is outside the scope of this book. | ||
If you want more information on Libgit2 itself, there's API documentation at https://libgit2.github.com/libgit2[], and a set of guides at https://libgit2.github.com/docs[]. | ||
For the other bindings, check the bundled README and tests; there are often small tutorials and pointers to further reading there. | ||
当然,完全阐述 Libgit2 的能力已超出本书范围。 | ||
如果你想了解更多关于 Libgit2 的信息,可以浏览它的 API 文档: https://libgit2.github.com/libgit2[], 以及一系列的指南: https://libgit2.github.com/docs[]. | ||
对于其它的绑定,检查附带的 README 和测试文件,那里通常有简易教程,以及指向拓展阅读的链接。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
打开一个仓库
看了一下前面的翻译,
repository
基本上译为仓库
,下面的repository
也是There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TRANSLATION_NOTES 要求
repository
翻译为版本库
的…… @fatjycThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IceNature 好吧,是我的问题。但是我粗略的看了一下,前面还是有很多没有按要求将
repository
翻译为版本库
的。例如
https://github.com/progit/progit2-zh/blob/master/book/02-git-basics/sections/getting-a-repository.asc#获取-git-仓库
https://github.com/progit/progit2-zh/blob/master/book/02-git-basics/sections/recording-changes.asc#记录每次更新到仓库
当然,这不在这篇的讨论范围了。。。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
仓库 和 版本库 的问题最终可能会定为仓库,请勿在这种定义上浪费时间,等后期统一处理。