Skip to content

Commit d79ca5f

Browse files
authored
feat(repository): add more options for init/open/clone repository (#53)
* add more open/init options * update
1 parent 75f893b commit d79ca5f

File tree

4 files changed

+273
-2
lines changed

4 files changed

+273
-2
lines changed

index.d.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,129 @@ export interface PruneOptions {
604604
}
605605
/** A listing of the possible states that a repository can be in. */
606606
export type RepositoryState = 'Clean' | 'Merge' | 'Revert' | 'RevertSequence' | 'CherryPick' | 'CherryPickSequence' | 'Bisect' | 'Rebase' | 'RebaseInteractive' | 'RebaseMerge' | 'ApplyMailbox' | 'ApplyMailboxOrRebase';
607+
/** Mode options for `RepositoryInitOptions`. */
608+
export const enum RepositoryInitMode {
609+
/** Use permissions configured by umask (default) */
610+
SharedUnmask = 0,
611+
/**
612+
* Use `--shared=group` behavior, chmod'ing the new repo to be
613+
* group writable and "g+sx" for sticky group assignment.
614+
*/
615+
SharedGroup = 1533,
616+
/** Use `--shared=all` behavior, adding world readability. */
617+
SharedAll = 1535
618+
}
607619
export interface RepositoryInitOptions {
620+
/**
621+
* Create a bare repository with no working directory.
622+
*
623+
* Defaults to `false`.
624+
*/
608625
bare?: boolean
626+
/**
627+
* Return an error if the repository path appears to already be a git
628+
* repository.
629+
*
630+
* Defaults to `false`.
631+
*/
632+
noReinit?: boolean
633+
/**
634+
* Normally a '/.git/' will be appended to the repo path for non-bare repos
635+
* (if it is not already there), but passing this flag prevents that
636+
* behavior.
637+
*
638+
* Defaults to `false`.
639+
*/
640+
noDotgitDir?: boolean
641+
/**
642+
* Make the repo path (and workdir path) as needed. The ".git" directory
643+
* will always be created regardless of this flag.
644+
*
645+
* Defaults to `true`.
646+
*/
647+
mkdir?: boolean
648+
/**
649+
* Make the repo path (and workdir path) as needed. The ".git" directory
650+
* will always be created regardless of this flag.
651+
*
652+
* Defaults to `true`.
653+
*/
654+
mkpath?: boolean
655+
/** Set to one of the `RepositoryInit` constants, or a custom value. */
656+
mode?: number
657+
/**
658+
* Enable or disable using external templates.
659+
*
660+
* If enabled, then the `template_path` option will be queried first, then
661+
* `init.templatedir` from the global config, and finally
662+
* `/usr/share/git-core-templates` will be used (if it exists).
663+
*
664+
* Defaults to `true`.
665+
*/
666+
externalTemplate?: boolean
667+
/**
668+
* When the `externalTemplate` option is set, this is the first location
669+
* to check for the template directory.
670+
*
671+
* If this is not configured, then the default locations will be searched
672+
* instead.
673+
*/
674+
templatePath?: string
675+
/**
676+
* The path to the working directory.
677+
*
678+
* If this is a relative path it will be evaluated relative to the repo
679+
* path. If this is not the "natural" working directory, a .git gitlink
680+
* file will be created here linking to the repo path.
681+
*/
682+
workdirPath?: string
683+
/**
684+
* If set, this will be used to initialize the "description" file in the
685+
* repository instead of using the template content.
686+
*/
687+
description?: string
688+
/**
689+
* The name of the head to point HEAD at.
690+
*
691+
* If not configured, this will be taken from your git configuration.
692+
* If this begins with `refs/` it will be used verbatim;
693+
* otherwise `refs/heads/` will be prefixed.
694+
*/
609695
initialHead?: string
696+
/**
697+
* If set, then after the rest of the repository initialization is
698+
* completed an `origin` remote will be added pointing to this URL.
699+
*/
610700
originUrl?: string
611701
}
702+
/** Options which can be used to configure how a repository is initialized. */
612703
export interface RepositoryOpenOptions {
704+
/**
705+
* If flags contains `RepositoryOpenFlags.NoSearch`, the path must point
706+
* directly to a repository; otherwise, this may point to a subdirectory
707+
* of a repository, and `open` will search up through parent
708+
* directories.
709+
*
710+
* If flags contains `RepositoryOpenFlags.CrossFS`, the search through parent
711+
* directories will not cross a filesystem boundary (detected when the
712+
* stat st_dev field changes).
713+
*
714+
* If flags contains `RepositoryOpenFlags.Bare`, force opening the repository as
715+
* bare even if it isn't, ignoring any working directory, and defer
716+
* loading the repository configuration for performance.
717+
*
718+
* If flags contains `RepositoryOpenFlags.NoDotgit`, don't try appending
719+
* `/.git` to `path`.
720+
*
721+
* If flags contains `RepositoryOpenFlags.FromEnv`, `open` will ignore
722+
* other flags and `ceilingDirs`, and respect the same environment
723+
* variables git does. Note, however, that `path` overrides `$GIT_DIR`.
724+
*/
613725
flags: number
726+
/**
727+
* ceiling_dirs specifies a list of paths that the search through parent
728+
* directories will stop before entering.
729+
*/
614730
ceilingDirs?: Array<string>
615731
}
616732
/** Flags for opening repository. */
@@ -627,7 +743,25 @@ export const enum RepositoryOpenFlags {
627743
FromEnv = 16
628744
}
629745
export interface RepositoryCloneOptions {
746+
/**
747+
* Indicate whether the repository will be cloned as a bare repository or
748+
* not.
749+
*/
750+
bare?: boolean
751+
/**
752+
* Specify the name of the branch to check out after the clone.
753+
*
754+
* If not specified, the remote's default branch will be used.
755+
*/
756+
branch?: string
757+
/**
758+
* Clone a remote repository, initialize and update its submodules
759+
* recursively.
760+
*
761+
* This is similar to `git clone --recursive`.
762+
*/
630763
recursive?: boolean
764+
/** Options which control the fetch. */
631765
fetch?: FetchOptions
632766
}
633767
/** Creates a new repository in the specified folder. */

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.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"scripts": {
3737
"prepublishOnly": "napi prepublish -t npm",
3838
"build": "napi build --platform --release --pipe=\"yarn transform:dts\"",
39-
"build:debug": "napi build --platform --pipe=\"yarn transform:dts\"",
39+
"build:debug": "DEBUG=\"napi:*\" napi build --platform --pipe=\"yarn transform:dts\"",
4040
"transform:dts": "jscodeshift -t transforms/dts.mjs index.d.ts",
4141
"check": "biome check",
4242
"check:fix": "biome check --write --unsafe"

src/repository.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,79 @@ impl From<git2::RepositoryState> for RepositoryState {
4040
}
4141
}
4242

43+
#[napi]
44+
#[repr(u32)]
45+
/// Mode options for `RepositoryInitOptions`.
46+
pub enum RepositoryInitMode {
47+
/// Use permissions configured by umask (default)
48+
SharedUnmask = 0,
49+
/// Use `--shared=group` behavior, chmod'ing the new repo to be
50+
/// group writable and "g+sx" for sticky group assignment.
51+
SharedGroup = 0o002775,
52+
/// Use `--shared=all` behavior, adding world readability.
53+
SharedAll = 0o002777,
54+
}
55+
4356
#[napi(object)]
4457
pub struct RepositoryInitOptions {
58+
/// Create a bare repository with no working directory.
59+
///
60+
/// Defaults to `false`.
4561
pub bare: Option<bool>,
62+
/// Return an error if the repository path appears to already be a git
63+
/// repository.
64+
///
65+
/// Defaults to `false`.
66+
pub no_reinit: Option<bool>,
67+
/// Normally a '/.git/' will be appended to the repo path for non-bare repos
68+
/// (if it is not already there), but passing this flag prevents that
69+
/// behavior.
70+
///
71+
/// Defaults to `false`.
72+
pub no_dotgit_dir: Option<bool>,
73+
/// Make the repo path (and workdir path) as needed. The ".git" directory
74+
/// will always be created regardless of this flag.
75+
///
76+
/// Defaults to `true`.
77+
pub mkdir: Option<bool>,
78+
/// Make the repo path (and workdir path) as needed. The ".git" directory
79+
/// will always be created regardless of this flag.
80+
///
81+
/// Defaults to `true`.
82+
pub mkpath: Option<bool>,
83+
/// Set to one of the `RepositoryInit` constants, or a custom value.
84+
pub mode: Option<u32>,
85+
/// Enable or disable using external templates.
86+
///
87+
/// If enabled, then the `template_path` option will be queried first, then
88+
/// `init.templatedir` from the global config, and finally
89+
/// `/usr/share/git-core-templates` will be used (if it exists).
90+
///
91+
/// Defaults to `true`.
92+
pub external_template: Option<bool>,
93+
/// When the `externalTemplate` option is set, this is the first location
94+
/// to check for the template directory.
95+
///
96+
/// If this is not configured, then the default locations will be searched
97+
/// instead.
98+
pub template_path: Option<String>,
99+
/// The path to the working directory.
100+
///
101+
/// If this is a relative path it will be evaluated relative to the repo
102+
/// path. If this is not the "natural" working directory, a .git gitlink
103+
/// file will be created here linking to the repo path.
104+
pub workdir_path: Option<String>,
105+
/// If set, this will be used to initialize the "description" file in the
106+
/// repository instead of using the template content.
107+
pub description: Option<String>,
108+
/// The name of the head to point HEAD at.
109+
///
110+
/// If not configured, this will be taken from your git configuration.
111+
/// If this begins with `refs/` it will be used verbatim;
112+
/// otherwise `refs/heads/` will be prefixed.
46113
pub initial_head: Option<String>,
114+
/// If set, then after the rest of the repository initialization is
115+
/// completed an `origin` remote will be added pointing to this URL.
47116
pub origin_url: Option<String>,
48117
}
49118

@@ -53,6 +122,33 @@ impl From<&RepositoryInitOptions> for git2::RepositoryInitOptions {
53122
if let Some(bare) = value.bare {
54123
opts.bare(bare);
55124
}
125+
if let Some(no_reinit) = value.no_reinit {
126+
opts.no_reinit(no_reinit);
127+
}
128+
if let Some(no_dotgit_dir) = value.no_dotgit_dir {
129+
opts.no_dotgit_dir(no_dotgit_dir);
130+
}
131+
if let Some(mkdir) = value.mkdir {
132+
opts.mkdir(mkdir);
133+
}
134+
if let Some(mkpath) = value.mkpath {
135+
opts.mkpath(mkpath);
136+
}
137+
if let Some(mode) = value.mode {
138+
opts.mode(git2::RepositoryInitMode::from_bits_truncate(mode));
139+
}
140+
if let Some(external_template) = value.external_template {
141+
opts.external_template(external_template);
142+
}
143+
if let Some(template_path) = &value.template_path {
144+
opts.template_path(Path::new(template_path));
145+
}
146+
if let Some(workdir_path) = &value.workdir_path {
147+
opts.workdir_path(Path::new(workdir_path));
148+
}
149+
if let Some(description) = &value.description {
150+
opts.description(description);
151+
}
56152
if let Some(ref initial_head) = value.initial_head {
57153
opts.initial_head(initial_head);
58154
}
@@ -64,8 +160,30 @@ impl From<&RepositoryInitOptions> for git2::RepositoryInitOptions {
64160
}
65161

66162
#[napi(object)]
163+
/// Options which can be used to configure how a repository is initialized.
67164
pub struct RepositoryOpenOptions {
165+
/// If flags contains `RepositoryOpenFlags.NoSearch`, the path must point
166+
/// directly to a repository; otherwise, this may point to a subdirectory
167+
/// of a repository, and `open` will search up through parent
168+
/// directories.
169+
///
170+
/// If flags contains `RepositoryOpenFlags.CrossFS`, the search through parent
171+
/// directories will not cross a filesystem boundary (detected when the
172+
/// stat st_dev field changes).
173+
///
174+
/// If flags contains `RepositoryOpenFlags.Bare`, force opening the repository as
175+
/// bare even if it isn't, ignoring any working directory, and defer
176+
/// loading the repository configuration for performance.
177+
///
178+
/// If flags contains `RepositoryOpenFlags.NoDotgit`, don't try appending
179+
/// `/.git` to `path`.
180+
///
181+
/// If flags contains `RepositoryOpenFlags.FromEnv`, `open` will ignore
182+
/// other flags and `ceilingDirs`, and respect the same environment
183+
/// variables git does. Note, however, that `path` overrides `$GIT_DIR`.
68184
pub flags: u32,
185+
/// ceiling_dirs specifies a list of paths that the search through parent
186+
/// directories will stop before entering.
69187
pub ceiling_dirs: Option<Vec<String>>,
70188
}
71189

@@ -87,7 +205,19 @@ pub enum RepositoryOpenFlags {
87205

88206
#[napi(object)]
89207
pub struct RepositoryCloneOptions {
208+
/// Indicate whether the repository will be cloned as a bare repository or
209+
/// not.
210+
pub bare: Option<bool>,
211+
/// Specify the name of the branch to check out after the clone.
212+
///
213+
/// If not specified, the remote's default branch will be used.
214+
pub branch: Option<String>,
215+
/// Clone a remote repository, initialize and update its submodules
216+
/// recursively.
217+
///
218+
/// This is similar to `git clone --recursive`.
90219
pub recursive: Option<bool>,
220+
/// Options which control the fetch.
91221
pub fetch: Option<FetchOptions>,
92222
}
93223

@@ -313,6 +443,12 @@ impl Task for CloneRepositoryTask {
313443
let mut builder = git2::build::RepoBuilder::new();
314444
let mut recursive = false;
315445
if let Some(opts) = &self.options {
446+
if let Some(bare) = opts.bare {
447+
builder.bare(bare);
448+
}
449+
if let Some(branch) = &opts.branch {
450+
builder.branch(branch);
451+
}
316452
if let Some(fetch) = &opts.fetch {
317453
let fetch_options = fetch.to_git2_fetch_options();
318454
builder.fetch_options(fetch_options);

0 commit comments

Comments
 (0)