72 Commits

Author SHA1 Message Date
9b4ed2837e Merge branch 'develop' 2022-12-12 17:41:41 +01:00
701e64df6f Release v0.7.12 2022-12-12 17:41:41 +01:00
23fc942db7 Warn on empty filters
Closes #29
2022-12-12 15:43:27 +01:00
38bba1472e Improve error messages during sync errors
Closes #46
2022-12-12 15:21:42 +01:00
7d131bbacf 'Enable deny_unknown_fields for all config structs 2022-12-12 15:10:00 +01:00
6e79dd318a Make clippy happy 2022-12-12 14:46:08 +01:00
5fc1d2148f Cargo.lock: Updating polling v2.3.0 -> v2.5.1 2022-12-12 14:41:07 +01:00
de184de5a0 Cargo.lock: Updating futures-io v0.3.24 -> v0.3.25 2022-12-12 14:41:07 +01:00
8a3b2ae1c5 Cargo.lock: Updating curl-sys v0.4.56+curl-7.83.1 -> v0.4.59+curl-7.86.0 2022-12-12 14:41:07 +01:00
93e38b0572 Cargo.lock: Updating cc v1.0.73 -> v1.0.77 2022-12-12 14:41:07 +01:00
43bbb8e143 Cargo.lock: Updating crossbeam-utils v0.8.12 -> v0.8.14 2022-12-12 14:41:07 +01:00
0fd9ce68b8 Cargo.lock: Updating async-channel v1.7.1 -> v1.8.0 2022-12-12 14:41:07 +01:00
68f2b81e3f dependencies: Update parse_link_header to 0.3.3 2022-12-12 14:41:07 +01:00
d7a39fa4e4 dependencies: Update serde_json to 1.0.89 2022-12-12 14:41:07 +01:00
1f646fd5f8 dependencies: Update serde_yaml to 0.9.14 2022-12-12 14:41:07 +01:00
96cbf8c568 dependencies: Update comfy-table to 6.1.3 2022-12-12 14:41:07 +01:00
bf199c1b17 dependencies: Update regex to 1.7.0 2022-12-12 14:41:07 +01:00
0f7a70c895 dependencies: Update clap to 4.0.29 2022-12-12 14:41:07 +01:00
3151b97bc0 dependencies: Update shellexpand to 3.0.0 2022-12-12 14:41:07 +01:00
8ce5cfecd4 dependencies: Update serde to 1.0.150 2022-12-12 13:55:05 +01:00
6da27c6444 Merge branch 'develop' 2022-12-12 13:53:02 +01:00
3026b3e6de Release v0.7.11 2022-12-12 13:53:02 +01:00
725414cc71 release-script: Fix missing newline 2022-12-12 13:43:34 +01:00
defb8fafca Merge branch 'develop' 2022-10-10 18:50:40 +02:00
f747c085c9 Release v0.7.10 2022-10-10 18:50:40 +02:00
85dd794b53 Cargo.lock: Updating tracing v0.1.36 -> v0.1.37 2022-10-10 18:06:27 +02:00
be8d85cb66 dependencies: Update serde_json to 1.0.86 2022-10-10 18:06:25 +02:00
0b7527fc7d dependencies: Update clap to 4.0.11 2022-10-10 18:06:25 +02:00
3a568a774a Remove init_worktree from sync config
It was currently unused and only confuses. The initialization of
worktrees can currently only be controlled via the `--init-worktree`
command line switch. This is unfortunate, but it's the only was to
handle it right now. Changing it would mean a restructure of the code,
mainly the `tree::sync_trees` function.
2022-10-06 12:59:56 +02:00
a6ecb66547 Merge branch 'develop' 2022-10-06 12:38:32 +02:00
8a04db8130 Release v0.7.9 2022-10-06 12:38:32 +02:00
d5bbbe6171 just: Use bash explicitly 2022-10-06 12:28:20 +02:00
c6a27525fd Remove unnecessary deref 2022-10-06 12:20:30 +02:00
5880066531 cli: Update code for clap v4 2022-10-06 12:17:26 +02:00
918b63047b Cargo.lock: Updating thiserror v1.0.35 -> v1.0.37 2022-10-06 11:36:53 +02:00
0fa2a65c81 Cargo.lock: Updating openssl-sys v0.9.75 -> v0.9.76 2022-10-06 11:36:52 +02:00
87d5b7ad85 Cargo.lock: Updating crossbeam-utils v0.8.11 -> v0.8.12 2022-10-06 11:36:50 +02:00
7db3596302 Cargo.lock: Updating smallvec v1.9.0 -> v1.10.0 2022-10-06 11:36:49 +02:00
e65c744f9c Cargo.lock: Updating jobserver v0.1.24 -> v0.1.25 2022-10-06 11:36:48 +02:00
bd79602d3a dependencies: Update console to 0.15.2 2022-10-06 11:36:47 +02:00
6e876aaefc dependencies: Update clap to 4.0.10 2022-10-06 11:36:47 +02:00
04753e8d9c Merge branch 'develop' 2022-09-23 07:19:03 +02:00
5811476e27 Release v0.7.8 2022-09-23 07:19:03 +02:00
5ac814b857 Cargo.lock: Updating idna v0.2.3 -> v0.3.0 2022-09-23 07:05:43 +02:00
3a87772606 Cargo.lock: Updating form_urlencoded v1.0.1 -> v1.1.0 2022-09-23 07:05:40 +02:00
001911bed9 Cargo.lock: Updating thiserror v1.0.32 -> v1.0.35 2022-09-23 07:05:37 +02:00
d1d729c33d Cargo.lock: Updating socket2 v0.4.6 -> v0.4.7 2022-09-23 07:05:35 +02:00
b4cabae4ec Cargo.lock: Updating lock_api v0.4.8 -> v0.4.9 2022-09-23 07:05:33 +02:00
196bbeb2c2 Cargo.lock: Updating aho-corasick v0.7.18 -> v0.7.19 2022-09-23 07:05:30 +02:00
4d60012f44 dependencies: Update serde_yaml to 0.9.13 2022-09-23 07:05:30 +02:00
b2f413b033 dependencies: Update clap to 3.2.22 2022-09-23 07:05:30 +02:00
c25bb8bf55 dependencies: Update serde to 1.0.145 2022-09-23 07:05:30 +02:00
3b923e3e13 Merge pull request #44 from vrischmann/name-in-error
catch the error returned by add_repo_status
2022-09-23 07:03:40 +02:00
Vincent Rischmann
061265bbd0 catch the error returned by add_repo_status
If add_repo_status returns an error it will eventually be printed to the
user but there won't be any repository information:

    [✘] Error getting status: No branch checked out

Catch the error earlier so we can print the repository name:

    [✘] Error: freebsd-src: Couldn't add repo status: No branch checked out
2022-09-22 21:10:16 +02:00
a08a8d2000 Merge branch 'develop' 2022-08-29 21:10:53 +02:00
fea0299c95 Release v0.7.7 2022-08-29 21:10:53 +02:00
444930199c Update README 2022-08-29 20:25:34 +02:00
95704b9a40 Cargo.lock: Updating pin-project v1.0.11 -> v1.0.12 2022-08-29 20:05:54 +02:00
8d300827d0 Cargo.lock: Updating futures-io v0.3.21 -> v0.3.24 2022-08-29 20:05:51 +02:00
9ab79b120a Cargo.lock: Updating fastrand v1.7.0 -> v1.8.0 2022-08-29 20:05:48 +02:00
8cc9470aca Cargo.lock: Updating curl v0.4.43 -> v0.4.44 2022-08-29 20:05:45 +02:00
9e95701a6e Cargo.lock: Updating crossbeam-utils v0.8.10 -> v0.8.11 2022-08-29 20:05:43 +02:00
fe90401688 Cargo.lock: Updating bytes v1.2.0 -> v1.2.1 2022-08-29 20:05:42 +02:00
aeaaee9915 Cargo.lock: Updating async-channel v1.6.1 -> v1.7.1 2022-08-29 20:05:41 +02:00
52b024c1ba dependencies: Update serde_json to 1.0.85 2022-08-29 20:05:40 +02:00
3a95613132 dependencies: Update serde_yaml to 0.9.10 2022-08-29 20:05:40 +02:00
2ea2c994d8 dependencies: Update comfy-table to 6.1.0 2022-08-29 20:05:40 +02:00
04686b6dfa dependencies: Update console to 0.15.1 2022-08-29 20:05:40 +02:00
78201d4759 dependencies: Update clap to 3.2.18 2022-08-29 20:05:40 +02:00
5fe6600dc3 dependencies: Update shellexpand to 2.1.2 2022-08-29 20:05:40 +02:00
2a65f78cd4 dependencies: Update git2 to 0.15.0 2022-08-29 20:05:40 +02:00
4852dad71e dependencies: Update serde to 1.0.144 2022-08-29 20:05:40 +02:00
17 changed files with 400 additions and 297 deletions

480
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "git-repo-manager"
version = "0.7.6"
version = "0.7.12"
edition = "2021"
authors = [
@@ -44,33 +44,33 @@ path = "src/grm/main.rs"
version = "=0.5.9"
[dependencies.serde]
version = "=1.0.140"
version = "=1.0.150"
features = ["derive"]
[dependencies.git2]
version = "=0.14.4"
version = "=0.15.0"
[dependencies.shellexpand]
version = "=2.1.0"
version = "=3.0.0"
[dependencies.clap]
version = "=3.2.14"
version = "=4.0.29"
features = ["derive", "cargo"]
[dependencies.console]
version = "=0.15.0"
version = "=0.15.2"
[dependencies.regex]
version = "=1.6.0"
version = "=1.7.0"
[dependencies.comfy-table]
version = "=6.0.0"
version = "=6.1.3"
[dependencies.serde_yaml]
version = "=0.8.26"
version = "=0.9.14"
[dependencies.serde_json]
version = "=1.0.82"
version = "=1.0.89"
[dependencies.isahc]
version = "=1.7.2"
@@ -78,7 +78,7 @@ default-features = false
features = ["json", "http2", "text-decoding"]
[dependencies.parse_link_header]
version = "=0.3.2"
version = "=0.3.3"
[dependencies.url-escape]
version = "=0.1.1"

View File

@@ -1,5 +1,7 @@
set positional-arguments
set shell := ["/bin/bash", "-c"]
static_target := "x86_64-unknown-linux-musl"
check: fmt-check lint test

View File

@@ -1,7 +1,10 @@
# GRM — Git Repository Manager
GRM helps you manage git repositories in a declarative way. Configure your
repositories in a [TOML](https://toml.io/) file, GRM does the rest.
repositories in a [TOML](https://toml.io/) or YAML file, GRM does the rest.
Also, GRM can be used to work with git worktrees in an opinionated,
straightforward fashion.
**Take a look at the [official documentation](https://hakoerber.github.io/git-repo-manager/)
for installation & quickstart.**
@@ -34,23 +37,26 @@ like Terraform for your local git repositories. Write a config, run the tool, an
your repos are ready. The only thing that is tracked by git it the list of
repositories itself.
# Future & Ideas
* Operations over all repos (e.g. pull)
* Show status of managed repositories (dirty, compare to remotes, ...)
# Optional Features
* Support multiple file formats (YAML, JSON).
* Add systemd timer unit to run regular syncs
# Crates
* [`toml`](https://docs.rs/toml/) for the configuration file
* [`serde`](https://docs.rs/serde/) because we're using Rust, after all
* [`git2`](https://docs.rs/git2/), a safe wrapper around `libgit2`, for all git operations
* [`clap`](https://docs.rs/clap/), [`console`](https://docs.rs/console/) and [`shellexpand`](https://docs.rs/shellexpand) for good UX
* [`toml`](https://docs.rs/toml/) for the configuration file.
* [`serde`](https://docs.rs/serde/), together with
[`serde_yaml`](https://docs.rs/serde_yaml/) and
[`serde_json`](https://docs.rs/serde_json/). Because we're using Rust, after
all.
* [`git2`](https://docs.rs/git2/), a safe wrapper around `libgit2`, for all git operations.
* [`clap`](https://docs.rs/clap/), [`console`](https://docs.rs/console/), [`comfy_table`](https://docs.rs/comfy-table/) and [`shellexpand`](https://docs.rs/shellexpand) for good UX.
* [`isahc`](https://docs.rs/isahc/) as the HTTP client for forge integrations.
# Links
* [crates.io](https://crates.io/crates/git-repo-manager)
# Mirrors
This repository can be found on multiple forges:
* https://github.com/hakoerber/git-repo-manager
* https://code.hkoerber.de/hannes/git-repo-manager/
* https://codeberg.org/hakoerber/git-repo-manager
* https://git.sr.ht/~hkoerber/git-repo-manager

View File

@@ -28,7 +28,7 @@ def get_temporary_directory(dir=None):
def grm(args, cwd=None, is_invalid=False):
cmd = subprocess.run([binary] + args, cwd=cwd, capture_output=True, text=True)
if not is_invalid:
assert "USAGE" not in cmd.stderr
assert "usage" not in cmd.stderr.lower()
print(f"grmcmd: {args}")
print(f"stdout:\n{cmd.stdout}")
print(f"stderr:\n{cmd.stderr}")

View File

@@ -5,9 +5,9 @@ from helpers import *
def test_invalid_command():
cmd = grm(["whatever"], is_invalid=True)
assert "USAGE" in cmd.stderr
assert "usage" in cmd.stderr.lower()
def test_help():
cmd = grm(["--help"])
assert "USAGE" in cmd.stdout
assert "usage" in cmd.stdout.lower()

View File

@@ -166,7 +166,7 @@ def test_repos_find_remote_no_filter(provider, configtype, default, use_config):
cmd = grm(args)
assert cmd.returncode == 0
assert len(cmd.stderr) == 0
assert "did not specify any filters" in cmd.stderr.lower()
if default or configtype == "toml":
output = toml.loads(cmd.stdout)

View File

@@ -67,7 +67,7 @@ fi
for remote in $(git remote); do
if git ls-remote --tags "${remote}" | grep -q "refs/tags/v${new_version}$"; then
printf 'Tag %s already exists on %s' "v${new_version}" "${remote}" >&2
printf 'Tag %s already exists on %s\n' "v${new_version}" "${remote}" >&2
exit 1
fi
done

View File

@@ -33,6 +33,7 @@ pub struct ConfigTrees {
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigProviderFilter {
pub access: Option<bool>,
pub owner: Option<bool>,
@@ -41,6 +42,7 @@ pub struct ConfigProviderFilter {
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConfigProvider {
pub provider: RemoteProvider,
pub token_command: String,
@@ -52,7 +54,6 @@ pub struct ConfigProvider {
pub api_url: Option<String>,
pub worktree: Option<bool>,
pub init_worktree: Option<bool>,
pub remote_name: Option<String>,
}
@@ -182,6 +183,12 @@ impl Config {
filters.access.unwrap_or(false),
);
if filter.empty() {
print_warning(
"The configuration does not contain any filters, so no repos will match",
);
}
let repos = match config.provider {
RemoteProvider::Github => {
match provider::Github::new(filter, token, config.api_url) {
@@ -241,7 +248,7 @@ impl Config {
pub fn normalize(&mut self) {
if let Config::ConfigTrees(config) = self {
let home = path::env_home().display().to_string();
let home = path::env_home();
for tree in &mut config.trees_mut().iter_mut() {
if tree.root.starts_with(&home) {
// The tilde is not handled differently, it's just a normal path component for `Path`.
@@ -299,7 +306,7 @@ pub fn read_config<'a, T>(path: &str) -> Result<T, String>
where
T: for<'de> serde::Deserialize<'de>,
{
let content = match std::fs::read_to_string(&path) {
let content = match std::fs::read_to_string(path) {
Ok(s) => s,
Err(e) => {
return Err(format!(

View File

@@ -1,4 +1,4 @@
use clap::{AppSettings, Parser};
use clap::Parser;
#[derive(Parser)]
#[clap(
@@ -7,7 +7,6 @@ use clap::{AppSettings, Parser};
author = clap::crate_authors!("\n"),
about = clap::crate_description!(),
long_version = clap::crate_version!(),
global_setting(AppSettings::DeriveDisplayOrder),
propagate_version = true,
)]
pub struct Opts {
@@ -65,7 +64,7 @@ pub struct FindLocalArgs {
pub path: String,
#[clap(
arg_enum,
value_enum,
short,
long,
help = "Format to produce",
@@ -85,7 +84,7 @@ pub struct FindConfigArgs {
pub config: String,
#[clap(
arg_enum,
value_enum,
short,
long,
help = "Format to produce",
@@ -100,14 +99,14 @@ pub struct FindRemoteArgs {
#[clap(short, long, help = "Path to the configuration file")]
pub config: Option<String>,
#[clap(arg_enum, short, long, help = "Remote provider to use")]
#[clap(value_enum, short, long, help = "Remote provider to use")]
pub provider: RemoteProvider,
#[clap(short, long, help = "Name of the remote to use")]
pub remote_name: Option<String>,
#[clap(
multiple_occurrences = true,
action = clap::ArgAction::Append,
name = "user",
long,
help = "Users to get repositories from"
@@ -115,7 +114,7 @@ pub struct FindRemoteArgs {
pub users: Vec<String>,
#[clap(
multiple_occurrences = true,
action = clap::ArgAction::Append,
name = "group",
long,
help = "Groups to get repositories from"
@@ -138,7 +137,7 @@ pub struct FindRemoteArgs {
pub root: String,
#[clap(
arg_enum,
value_enum,
short,
long,
help = "Format to produce",
@@ -149,11 +148,10 @@ pub struct FindRemoteArgs {
#[clap(
long,
help = "Use worktree setup for repositories",
possible_values = &["true", "false"],
value_parser = ["true", "false"],
default_value = "false",
default_missing_value = "true",
min_values = 0,
max_values = 1,
num_args = 0..=1,
)]
pub worktree: String,
@@ -174,12 +172,11 @@ pub struct Config {
#[clap(
long,
value_parser = ["true", "false"],
help = "Check out the default worktree after clone",
possible_values = &["true", "false"],
default_value = "true",
default_missing_value = "true",
min_values = 0,
max_values = 1,
num_args = 0..=1,
)]
pub init_worktree: String,
}
@@ -189,14 +186,14 @@ pub type RemoteProvider = super::provider::RemoteProvider;
#[derive(Parser)]
#[clap()]
pub struct SyncRemoteArgs {
#[clap(arg_enum, short, long, help = "Remote provider to use")]
#[clap(value_enum, short, long, help = "Remote provider to use")]
pub provider: RemoteProvider,
#[clap(short, long, help = "Name of the remote to use")]
pub remote_name: Option<String>,
#[clap(
multiple_occurrences = true,
action = clap::ArgAction::Append,
name = "user",
long,
help = "Users to get repositories from"
@@ -204,7 +201,7 @@ pub struct SyncRemoteArgs {
pub users: Vec<String>,
#[clap(
multiple_occurrences = true,
action = clap::ArgAction::Append,
name = "group",
long,
help = "Groups to get repositories from"
@@ -229,11 +226,10 @@ pub struct SyncRemoteArgs {
#[clap(
long,
help = "Use worktree setup for repositories",
possible_values = &["true", "false"],
value_parser = ["true", "false"],
default_value = "false",
default_missing_value = "true",
min_values = 0,
max_values = 1,
num_args = 0..=1,
)]
pub worktree: String,
@@ -243,11 +239,10 @@ pub struct SyncRemoteArgs {
#[clap(
long,
help = "Check out the default worktree after clone",
possible_values = &["true", "false"],
value_parser = ["true", "false"],
default_value = "true",
default_missing_value = "true",
min_values = 0,
max_values = 1,
num_args = 0..=1,
)]
pub init_worktree: String,
}
@@ -259,7 +254,7 @@ pub struct OptionalConfig {
pub config: Option<String>,
}
#[derive(clap::ArgEnum, Clone)]
#[derive(clap::ValueEnum, Clone)]
pub enum ConfigFormat {
Yaml,
Toml,
@@ -299,7 +294,7 @@ pub struct WorktreeAddArgs {
#[clap(short = 't', long = "track", help = "Remote branch to track")]
pub track: Option<String>,
#[clap(long = "--no-track", help = "Disable tracking")]
#[clap(long = "no-track", help = "Disable tracking")]
pub no_track: bool,
}
#[derive(Parser)]
@@ -328,22 +323,19 @@ pub struct WorktreeFetchArgs {}
#[derive(Parser)]
pub struct WorktreePullArgs {
#[clap(long = "--rebase", help = "Perform a rebase instead of a fast-forward")]
#[clap(long = "rebase", help = "Perform a rebase instead of a fast-forward")]
pub rebase: bool,
#[clap(long = "--stash", help = "Stash & unstash changes before & after pull")]
#[clap(long = "stash", help = "Stash & unstash changes before & after pull")]
pub stash: bool,
}
#[derive(Parser)]
pub struct WorktreeRebaseArgs {
#[clap(long = "--pull", help = "Perform a pull before rebasing")]
#[clap(long = "pull", help = "Perform a pull before rebasing")]
pub pull: bool,
#[clap(long = "--rebase", help = "Perform a rebase when doing a pull")]
#[clap(long = "rebase", help = "Perform a rebase when doing a pull")]
pub rebase: bool,
#[clap(
long = "--stash",
help = "Stash & unstash changes before & after rebase"
)]
#[clap(long = "stash", help = "Stash & unstash changes before & after rebase")]
pub stash: bool,
}

View File

@@ -38,7 +38,7 @@ fn main() {
}
}
Err(error) => {
print_error(&format!("Error syncing trees: {}", error));
print_error(&format!("Sync error: {}", error));
process::exit(1);
}
}
@@ -55,6 +55,10 @@ fn main() {
let filter =
provider::Filter::new(args.users, args.groups, args.owner, args.access);
if filter.empty() {
print_warning("You did not specify any filters, so no repos will match");
}
let worktree = args.worktree == "true";
let repos = match args.provider {
@@ -62,7 +66,7 @@ fn main() {
match provider::Github::new(filter, token, args.api_url) {
Ok(provider) => provider,
Err(error) => {
print_error(&format!("Error: {}", error));
print_error(&format!("Sync error: {}", error));
process::exit(1);
}
}
@@ -76,7 +80,7 @@ fn main() {
match provider::Gitlab::new(filter, token, args.api_url) {
Ok(provider) => provider,
Err(error) => {
print_error(&format!("Error: {}", error));
print_error(&format!("Sync error: {}", error));
process::exit(1);
}
}
@@ -112,13 +116,13 @@ fn main() {
}
}
Err(error) => {
print_error(&format!("Error syncing trees: {}", error));
print_error(&format!("Sync error: {}", error));
process::exit(1);
}
}
}
Err(error) => {
print_error(&format!("Error: {}", error));
print_error(&format!("Sync error: {}", error));
process::exit(1);
}
}
@@ -278,6 +282,10 @@ fn main() {
filters.access.unwrap_or(false),
);
if filter.empty() {
print_warning("You did not specify any filters, so no repos will match");
}
let repos = match config.provider {
provider::RemoteProvider::Github => {
match match provider::Github::new(filter, token, config.api_url) {
@@ -383,6 +391,10 @@ fn main() {
let filter =
provider::Filter::new(args.users, args.groups, args.owner, args.access);
if filter.empty() {
print_warning("You did not specify any filters, so no repos will match");
}
let worktree = args.worktree == "true";
let repos = match args.provider {

View File

@@ -106,7 +106,7 @@ fn find_repos(root: &Path) -> Result<Option<(Vec<repo::Repo>, Vec<String>, bool)
},
)
} else {
let name = path.strip_prefix(&root).unwrap();
let name = path.strip_prefix(root).unwrap();
let namespace = name.parent().unwrap();
(
if namespace != Path::new("") {

View File

@@ -47,9 +47,9 @@ pub fn path_as_string(path: &Path) -> String {
path.to_path_buf().into_os_string().into_string().unwrap()
}
pub fn env_home() -> PathBuf {
pub fn env_home() -> String {
match std::env::var("HOME") {
Ok(path) => Path::new(&path).to_path_buf(),
Ok(path) => path,
Err(e) => {
print_error(&format!("Unable to read HOME: {}", e));
process::exit(1);
@@ -58,16 +58,12 @@ pub fn env_home() -> PathBuf {
}
pub fn expand_path(path: &Path) -> PathBuf {
fn home_dir() -> Option<PathBuf> {
Some(env_home())
}
let expanded_path = match shellexpand::full_with_context(
&path_as_string(path),
home_dir,
|| Some(env_home()),
|name| -> Result<Option<String>, &'static str> {
match name {
"HOME" => Ok(Some(path_as_string(home_dir().unwrap().as_path()))),
"HOME" => Ok(Some(env_home())),
_ => Ok(None),
}
},

View File

@@ -16,7 +16,7 @@ use std::collections::HashMap;
const DEFAULT_REMOTE_NAME: &str = "origin";
#[derive(Debug, Deserialize, Serialize, clap::ArgEnum, Clone)]
#[derive(Debug, Deserialize, Serialize, clap::ValueEnum, Clone)]
pub enum RemoteProvider {
#[serde(alias = "github", alias = "GitHub")]
Github,
@@ -89,6 +89,10 @@ impl Filter {
access,
}
}
pub fn empty(&self) -> bool {
self.users.is_empty() && self.groups.is_empty() && !self.owner && !self.access
}
}
pub enum ApiErrorResponse<T>
@@ -270,12 +274,16 @@ pub trait Provider {
}
for group in &self.filter().groups {
let group_projects = self
.get_group_projects(group)
.map_err(|error| match error {
ApiErrorResponse::Json(x) => x.to_string(),
ApiErrorResponse::String(s) => s,
})?;
let group_projects = self.get_group_projects(group).map_err(|error| {
format!(
"group \"{}\": {}",
group,
match error {
ApiErrorResponse::Json(x) => x.to_string(),
ApiErrorResponse::String(s) => s,
}
)
})?;
for group_project in group_projects {
let mut already_present = false;
for repo in &repos {

View File

@@ -785,7 +785,7 @@ impl RepoHandle {
))
})?;
for entry in match std::fs::read_dir(&root_dir) {
for entry in match std::fs::read_dir(root_dir) {
Ok(iterator) => iterator,
Err(error) => {
return Err(WorktreeConversionFailureReason::Error(format!(
@@ -1343,7 +1343,7 @@ impl RepoHandle {
},
})
{
let repo_dir = &directory.join(&worktree.name());
let repo_dir = &directory.join(worktree.name());
if repo_dir.exists() {
match self.remove_worktree(
directory,
@@ -1387,12 +1387,12 @@ impl RepoHandle {
.map_err(|error| format!("Getting worktrees failed: {}", error))?;
let mut unmanaged_worktrees = Vec::new();
for entry in std::fs::read_dir(&directory).map_err(|error| error.to_string())? {
for entry in std::fs::read_dir(directory).map_err(|error| error.to_string())? {
let dirname = path::path_as_string(
entry
.map_err(|error| error.to_string())?
.path()
.strip_prefix(&directory)
.strip_prefix(directory)
// that unwrap() is safe as each entry is
// guaranteed to be a subentry of &directory
.unwrap(),

View File

@@ -111,7 +111,7 @@ pub fn get_worktree_status_table(
add_worktree_table_header(&mut table);
for worktree in &worktrees {
let worktree_dir = &directory.join(&worktree.name());
let worktree_dir = &directory.join(worktree.name());
if worktree_dir.exists() {
let repo = match repo::RepoHandle::open(worktree_dir, false) {
Ok(repo) => repo,
@@ -185,7 +185,11 @@ pub fn get_status_table(config: config::Config) -> Result<(Vec<Table>, Vec<Strin
}
};
add_repo_status(&mut table, &repo.name, &repo_handle, repo.worktree_setup)?;
if let Err(err) =
add_repo_status(&mut table, &repo.name, &repo_handle, repo.worktree_setup)
{
errors.push(format!("{}: Couldn't add repo status: {}", &repo.name, err));
}
}
tables.push(table);

View File

@@ -372,7 +372,7 @@ impl<'a> Worktree<'a, WithRemoteTrackingBranch<'a>> {
// TECHDEBT
// We must not call this with `Some()` without a valid target.
// I'm sure this can be improved, just not sure how.
&*self.extra.target_commit.unwrap(),
&self.extra.target_commit.unwrap(),
)?
};