Skip to content

Commit bc0b2c7

Browse files
authored
feat: add annotated commit feature (#126)
1 parent c063836 commit bc0b2c7

File tree

6 files changed

+405
-1
lines changed

6 files changed

+405
-1
lines changed

index.d.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,45 @@ export interface CreateLightweightTagOptions {
17151715
* - `PostOrder` : Runs the traversal in post-order.
17161716
*/
17171717
export type TreeWalkMode = 'PreOrder' | 'PostOrder';
1718+
/**
1719+
* A structure to represent an annotated commit, the input to merge and rebase.
1720+
*
1721+
* An annotated commit contains information about how it was looked up, which
1722+
* may be useful for functions like merge or rebase to provide context to the
1723+
* operation.
1724+
*/
1725+
export declare class AnnotatedCommit {
1726+
/**
1727+
* Gets the commit ID that the given Annotated Commit refers to.
1728+
*
1729+
* @category AnnotatedCommit/Methods
1730+
* @signature
1731+
* ```ts
1732+
* class AnnotatedCommit {
1733+
* id(): string;
1734+
* }
1735+
* ```
1736+
*
1737+
* @returns The commit ID that this Annotated Commit refers to.
1738+
*/
1739+
id(): string
1740+
/**
1741+
* Get the refname that the given Annotated Commit refers to.
1742+
*
1743+
* @category AnnotatedCommit/Methods
1744+
* @signature
1745+
* ```ts
1746+
* class AnnotatedCommit {
1747+
* refname(): string | null;
1748+
* }
1749+
* ```
1750+
*
1751+
* @returns The refname that this Annotated Commit refers to. If this created from a reference,
1752+
* the return value is `null`.
1753+
* @throws Throws error if the refname is not valid utf-8.
1754+
*/
1755+
refname(): string | null
1756+
}
17181757
/** A wrapper around git2::Blame providing Node.js bindings */
17191758
export declare class Blame {
17201759
/**
@@ -3931,6 +3970,57 @@ export declare class Remote {
39313970
* This class corresponds to a git repository in libgit2.
39323971
*/
39333972
export declare class Repository {
3973+
/**
3974+
* Creates an Annotated Commit from the given commit.
3975+
*
3976+
* @category Repository/Methods
3977+
* @signature
3978+
* ```ts
3979+
* class Repository {
3980+
* getAnnotatedCommit(commit: Commit): AnnotatedCommit;
3981+
* }
3982+
* ```
3983+
*
3984+
* @param {Commit} commit - Commit to creates a Annotated Commit.
3985+
* @returns An Annotated Commit created from commit.
3986+
*/
3987+
getAnnotatedCommit(commit: Commit): AnnotatedCommit
3988+
/**
3989+
* Creates a Annotated Commit from the given reference.
3990+
*
3991+
* @category Repository/Methods
3992+
* @signature
3993+
* ```ts
3994+
* class Repository {
3995+
* getAnnotatedCommitFromReference(reference: Reference): AnnotatedCommit;
3996+
* }
3997+
* ```
3998+
*
3999+
* @param {Reference} reference - Reference to creates a Annotated Commit.
4000+
* @returns An Annotated Commit created from reference.
4001+
*/
4002+
getAnnotatedCommitFromReference(reference: GitReference): AnnotatedCommit
4003+
/**
4004+
* Creates a Annotated Commit from `FETCH_HEAD`.
4005+
*
4006+
* @category Repository/Methods
4007+
* @signature
4008+
* ```ts
4009+
* class Repository {
4010+
* getAnnotatedCommitFromFetchHead(
4011+
* branchName: string,
4012+
* remoteUrl: string,
4013+
* id: string,
4014+
* ): AnnotatedCommit;
4015+
* }
4016+
* ```
4017+
*
4018+
* @param {String} branchName - Name of the remote branch.
4019+
* @param {String} remoteUrl - Url of the remote.
4020+
* @param {String} id - The commit object id of the remote branch.
4021+
* @returns An Annotated Commit created from `FETCH_HEAD`.
4022+
*/
4023+
getAnnotatedCommitFromFetchHead(branchName: string, remoteUrl: string, id: string): AnnotatedCommit
39344024
/**
39354025
* Creates a blame object for the file at the given path
39364026
*
@@ -4701,6 +4791,64 @@ export declare class Repository {
47014791
* @param {string} refname - Specified reference to point into `HEAD`.
47024792
*/
47034793
setHead(refname: string): void
4794+
/**
4795+
* Determines whether the repository `HEAD` is detached.
4796+
*
4797+
* @category Repository/Methods
4798+
* @signature
4799+
* ```ts
4800+
* class Repository {
4801+
* headDetached(): boolean;
4802+
* }
4803+
* ```
4804+
*
4805+
* @returns Returns `true` if the repository `HEAD` is detached.
4806+
*/
4807+
headDetached(): boolean
4808+
/**
4809+
* Make the repository HEAD directly point to the commit.
4810+
*
4811+
* If the provided commitish cannot be found in the repository, the HEAD
4812+
* is unaltered and an error is returned.
4813+
*
4814+
* If the provided commitish cannot be peeled into a commit, the HEAD is
4815+
* unaltered and an error is returned.
4816+
*
4817+
* Otherwise, the HEAD will eventually be detached and will directly point
4818+
* to the peeled commit.
4819+
*
4820+
* @category Repository/Methods
4821+
* @signature
4822+
* ```ts
4823+
* class Repository {
4824+
* setHeadDetached(commitish: Commit): void;
4825+
* }
4826+
* ```
4827+
*
4828+
* @param {Commit} commitish - A Commit which the HEAD should point to.
4829+
*/
4830+
setHeadDetached(commit: Commit): void
4831+
/**
4832+
* Make the repository HEAD directly point to the commit.
4833+
*
4834+
* If the provided commitish cannot be found in the repository, the HEAD
4835+
* is unaltered and an error is returned.
4836+
* If the provided commitish cannot be peeled into a commit, the HEAD is
4837+
* unaltered and an error is returned.
4838+
* Otherwise, the HEAD will eventually be detached and will directly point
4839+
* to the peeled commit.
4840+
*
4841+
* @category Repository/Methods
4842+
* @signature
4843+
* ```ts
4844+
* class Repository {
4845+
* setHeadDetachedFromAnnotated(commitish: AnnotatedCommit): void;
4846+
* }
4847+
* ```
4848+
*
4849+
* @param {AnnotatedCommit} commitish - An Annotated Commit which the HEAD should point to.
4850+
*/
4851+
setHeadDetachedFromAnnotated(commitish: AnnotatedCommit): void
47044852
/**
47054853
* Extract a signature from an object identified by its ID.
47064854
*

index.js

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/annotated_commit.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use crate::commit::Commit;
2+
use crate::reference::Reference as GitReference;
3+
use crate::repository::Repository;
4+
use napi::bindgen_prelude::*;
5+
use napi_derive::napi;
6+
7+
#[napi]
8+
/// A structure to represent an annotated commit, the input to merge and rebase.
9+
///
10+
/// An annotated commit contains information about how it was looked up, which
11+
/// may be useful for functions like merge or rebase to provide context to the
12+
/// operation.
13+
pub struct AnnotatedCommit {
14+
pub(crate) from_ref: bool,
15+
pub(crate) inner: SharedReference<Repository, git2::AnnotatedCommit<'static>>,
16+
}
17+
18+
#[napi]
19+
impl AnnotatedCommit {
20+
#[napi]
21+
/// Gets the commit ID that the given Annotated Commit refers to.
22+
///
23+
/// @category AnnotatedCommit/Methods
24+
/// @signature
25+
/// ```ts
26+
/// class AnnotatedCommit {
27+
/// id(): string;
28+
/// }
29+
/// ```
30+
///
31+
/// @returns The commit ID that this Annotated Commit refers to.
32+
pub fn id(&self) -> String {
33+
self.inner.id().to_string()
34+
}
35+
36+
#[napi]
37+
/// Get the refname that the given Annotated Commit refers to.
38+
///
39+
/// @category AnnotatedCommit/Methods
40+
/// @signature
41+
/// ```ts
42+
/// class AnnotatedCommit {
43+
/// refname(): string | null;
44+
/// }
45+
/// ```
46+
///
47+
/// @returns The refname that this Annotated Commit refers to. If this created from a reference,
48+
/// the return value is `null`.
49+
/// @throws Throws error if the refname is not valid utf-8.
50+
pub fn refname(&self) -> crate::Result<Option<String>> {
51+
// If you created an Annotated Commit from a commit, there is no refname.
52+
// Since the `.refname()` method will cause a panic in `.unwrap()`, so we have to check
53+
// that this annotated commit is created from a reference explicitly.
54+
if self.from_ref {
55+
let refname = std::str::from_utf8(self.inner.refname_bytes())?;
56+
return Ok(Some(refname.to_string()));
57+
}
58+
Ok(None)
59+
}
60+
}
61+
62+
#[napi]
63+
impl Repository {
64+
#[napi]
65+
/// Creates an Annotated Commit from the given commit.
66+
///
67+
/// @category Repository/Methods
68+
/// @signature
69+
/// ```ts
70+
/// class Repository {
71+
/// getAnnotatedCommit(commit: Commit): AnnotatedCommit;
72+
/// }
73+
/// ```
74+
///
75+
/// @param {Commit} commit - Commit to creates a Annotated Commit.
76+
/// @returns An Annotated Commit created from commit.
77+
pub fn get_annotated_commit(
78+
&self,
79+
commit: &Commit,
80+
this: Reference<Repository>,
81+
env: Env,
82+
) -> crate::Result<AnnotatedCommit> {
83+
let oid = commit.inner.id();
84+
let inner = this.share_with(env, |repo| {
85+
repo
86+
.inner
87+
.find_annotated_commit(oid)
88+
.map_err(crate::Error::from)
89+
.map_err(|e| e.into())
90+
})?;
91+
Ok(AnnotatedCommit { from_ref: false, inner })
92+
}
93+
94+
#[napi]
95+
/// Creates a Annotated Commit from the given reference.
96+
///
97+
/// @category Repository/Methods
98+
/// @signature
99+
/// ```ts
100+
/// class Repository {
101+
/// getAnnotatedCommitFromReference(reference: Reference): AnnotatedCommit;
102+
/// }
103+
/// ```
104+
///
105+
/// @param {Reference} reference - Reference to creates a Annotated Commit.
106+
/// @returns An Annotated Commit created from reference.
107+
pub fn get_annotated_commit_from_reference(
108+
&self,
109+
reference: &GitReference,
110+
this: Reference<Repository>,
111+
env: Env,
112+
) -> crate::Result<AnnotatedCommit> {
113+
let inner = this.share_with(env, |repo| {
114+
repo
115+
.inner
116+
.reference_to_annotated_commit(&reference.inner)
117+
.map_err(crate::Error::from)
118+
.map_err(|e| e.into())
119+
})?;
120+
Ok(AnnotatedCommit { from_ref: true, inner })
121+
}
122+
123+
#[napi]
124+
/// Creates a Annotated Commit from `FETCH_HEAD`.
125+
///
126+
/// @category Repository/Methods
127+
/// @signature
128+
/// ```ts
129+
/// class Repository {
130+
/// getAnnotatedCommitFromFetchHead(
131+
/// branchName: string,
132+
/// remoteUrl: string,
133+
/// id: string,
134+
/// ): AnnotatedCommit;
135+
/// }
136+
/// ```
137+
///
138+
/// @param {String} branchName - Name of the remote branch.
139+
/// @param {String} remoteUrl - Url of the remote.
140+
/// @param {String} id - The commit object id of the remote branch.
141+
/// @returns An Annotated Commit created from `FETCH_HEAD`.
142+
pub fn get_annotated_commit_from_fetch_head(
143+
&self,
144+
branch_name: String,
145+
remote_url: String,
146+
id: String,
147+
this: Reference<Repository>,
148+
env: Env,
149+
) -> crate::Result<AnnotatedCommit> {
150+
let oid = git2::Oid::from_str(&id)?;
151+
let inner = this.share_with(env, |repo| {
152+
repo
153+
.inner
154+
.annotated_commit_from_fetchhead(&branch_name, &remote_url, &oid)
155+
.map_err(crate::Error::from)
156+
.map_err(|e| e.into())
157+
})?;
158+
Ok(AnnotatedCommit { from_ref: true, inner })
159+
}
160+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![deny(clippy::all)]
22

3+
pub mod annotated_commit;
34
pub mod blame;
45
pub mod blob;
56
pub mod branch;

0 commit comments

Comments
 (0)