25 Commits

Author SHA1 Message Date
b9051d5afb Merge branch 'develop' 2023-11-06 20:18:10 +01:00
6c6295651f Release v0.7.15 2023-11-06 20:18:10 +01:00
8c418ff846 Update dependencies 2023-11-06 20:17:18 +01:00
29b3bd3581 Merge pull request #63 from jgarte/jgarte-patch-1
Fix typo
2023-08-28 11:00:06 +02:00
jgart
012c6efb03 Fix typo 2023-08-28 01:00:10 -05:00
241bf473a7 Merge branch 'develop' 2023-08-09 00:32:33 +02:00
8fd663462e Release v0.7.14 2023-08-09 00:32:33 +02:00
4beacbf65d Reformat with new black version 2023-08-09 00:30:57 +02:00
102f5561a8 Use new compose call 2023-08-09 00:30:57 +02:00
e04f065d42 Drop nightly requirement 2023-08-09 00:30:57 +02:00
941dd50868 Cargo.lock: Updating pin-project v1.0.12 -> v1.1.3 2023-08-09 00:30:57 +02:00
d20dabc91e Cargo.lock: Updating pin-project-lite v0.2.9 -> v0.2.11 2023-08-09 00:30:57 +02:00
0e63a1c6bf Cargo.lock: Updating curl-sys v0.4.61+curl-8.0.1 -> v0.4.65+curl-8.2.1 2023-08-09 00:30:57 +02:00
9792c09850 Cargo.lock: Updating async-channel v1.8.0 -> v1.9.0 2023-08-09 00:30:57 +02:00
a1519a6bc5 dependencies: Update serde_json to 1.0.104 2023-08-09 00:30:57 +02:00
36535dcaec dependencies: Update serde_yaml to 0.9.25 2023-08-09 00:30:57 +02:00
32f94b1ef5 dependencies: Update comfy-table to 7.0.1 2023-08-09 00:30:57 +02:00
913df16f28 dependencies: Update regex to 1.9.3 2023-08-09 00:30:57 +02:00
f66a512a83 dependencies: Update console to 0.15.7 2023-08-09 00:30:57 +02:00
de15e799ac dependencies: Update clap to 4.3.21 2023-08-09 00:30:57 +02:00
a8736ed37f dependencies: Update git2 to 0.17.2 2023-08-09 00:30:57 +02:00
1a45887fb6 dependencies: Update serde to 1.0.183 2023-08-09 00:30:57 +02:00
9403156edf dependencies: Update toml to 0.7.6 2023-08-09 00:30:57 +02:00
21e3a9b9bb Merge branch 'develop' 2023-05-06 19:15:46 +02:00
ca0c9c28fd Release v0.7.13 2023-05-06 19:15:46 +02:00
15 changed files with 290 additions and 431 deletions

603
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "git-repo-manager" name = "git-repo-manager"
version = "0.7.12" version = "0.7.15"
edition = "2021" edition = "2021"
authors = [ authors = [
@@ -23,7 +23,7 @@ repository = "https://github.com/hakoerber/git-repo-manager"
readme = "README.md" readme = "README.md"
# Required for `std::path::Path::is_symlink()`. Will be released with 1.57. # Required for `std::path::Path::is_symlink()`. Will be released with 1.57.
rust-version = "1.57" rust-version = "1.58"
license = "GPL-3.0-only" license = "GPL-3.0-only"
@@ -41,36 +41,36 @@ path = "src/grm/main.rs"
[dependencies] [dependencies]
[dependencies.toml] [dependencies.toml]
version = "=0.7.3" version = "=0.8.6"
[dependencies.serde] [dependencies.serde]
version = "=1.0.162" version = "=1.0.190"
features = ["derive"] features = ["derive"]
[dependencies.git2] [dependencies.git2]
version = "=0.17.1" version = "=0.18.1"
[dependencies.shellexpand] [dependencies.shellexpand]
version = "=3.1.0" version = "=3.1.0"
[dependencies.clap] [dependencies.clap]
version = "=4.2.7" version = "=4.4.7"
features = ["derive", "cargo"] features = ["derive", "cargo"]
[dependencies.console] [dependencies.console]
version = "=0.15.5" version = "=0.15.7"
[dependencies.regex] [dependencies.regex]
version = "=1.8.1" version = "=1.10.2"
[dependencies.comfy-table] [dependencies.comfy-table]
version = "=6.1.4" version = "=7.1.0"
[dependencies.serde_yaml] [dependencies.serde_yaml]
version = "=0.9.21" version = "=0.9.27"
[dependencies.serde_json] [dependencies.serde_json]
version = "=1.0.96" version = "=1.0.108"
[dependencies.isahc] [dependencies.isahc]
version = "=1.7.2" version = "=1.7.2"

View File

@@ -4,7 +4,7 @@ set shell := ["/bin/bash", "-c"]
static_target := "x86_64-unknown-linux-musl" static_target := "x86_64-unknown-linux-musl"
cargo := "cargo +nightly" cargo := "cargo"
check: fmt-check lint test check: fmt-check lint test
{{cargo}} check {{cargo}} check
@@ -76,14 +76,14 @@ test-integration:
test-e2e +tests=".": test-binary test-e2e +tests=".": test-binary
cd ./e2e_tests \ cd ./e2e_tests \
&& docker-compose rm --stop -f \ && docker compose rm --stop -f \
&& docker-compose build \ && docker compose build \
&& docker-compose run \ && docker compose run \
--rm \ --rm \
-v $PWD/../target/x86_64-unknown-linux-musl/e2e-tests/grm:/grm \ -v $PWD/../target/x86_64-unknown-linux-musl/e2e-tests/grm:/grm \
pytest \ pytest \
"GRM_BINARY=/grm ALTERNATE_DOMAIN=alternate-rest python3 -m pytest --exitfirst -p no:cacheprovider --color=yes "$@"" \ "GRM_BINARY=/grm ALTERNATE_DOMAIN=alternate-rest python3 -m pytest --exitfirst -p no:cacheprovider --color=yes "$@"" \
&& docker-compose rm --stop -f && docker compose rm --stop -f
update-dependencies: update-cargo-dependencies update-dependencies: update-cargo-dependencies

View File

@@ -34,7 +34,7 @@ in once place?
This is how GRM came to be. I'm a fan of infrastructure-as-code, and GRM is a bit This is how GRM came to be. I'm a fan of infrastructure-as-code, and GRM is a bit
like Terraform for your local git repositories. Write a config, run the tool, and like Terraform for your local git repositories. Write a config, run the tool, and
your repos are ready. The only thing that is tracked by git it the list of your repos are ready. The only thing that is tracked by git is the list of
repositories itself. repositories itself.
# Crates # Crates

View File

@@ -93,15 +93,7 @@ for tier in ["dependencies", "dev-dependencies"]:
try: try:
cmd = subprocess.run( cmd = subprocess.run(
[ ["cargo", "update", "--offline", "--aggressive", "--package", name],
"cargo",
"update",
"-Z",
"no-index-update",
"--aggressive",
"--package",
name,
],
check=True, check=True,
capture_output=True, capture_output=True,
text=True, text=True,
@@ -135,15 +127,7 @@ while True:
spec = f"{package['name']}:{package['version']}" spec = f"{package['name']}:{package['version']}"
try: try:
cmd = subprocess.run( cmd = subprocess.run(
[ ["cargo", "update", "--offline", "--aggressive", "--package", spec],
"cargo",
"update",
"-Z",
"no-index-update",
"--aggressive",
"--package",
spec,
],
check=True, check=True,
capture_output=True, capture_output=True,
text=True, text=True,

View File

@@ -28,7 +28,7 @@ Feature branches are not required, there are also changes happening directly on
You will need the following tools: You will need the following tools:
* Rust (obviously) (easiest via `rustup`), with the nightly toolchain * Rust (obviously) (easiest via `rustup`)
* Python3 * Python3
* [`just`](https://github.com/casey/just), a command runner like `make`. See * [`just`](https://github.com/casey/just), a command runner like `make`. See
[here](https://github.com/casey/just#installation) for installation [here](https://github.com/casey/just#installation) for installation
@@ -52,18 +52,3 @@ mvdan.cc/sh/v3/cmd/shfmt@latest`, depending on your go build environment.
For details about rustup and the toolchains, see [the installation For details about rustup and the toolchains, see [the installation
section](./installation.md). section](./installation.md).
## FAQ
### Why nightly?
For now, GRM requires the nightly toolchain for two reasons:
* [`io_error_more`](https://github.com/rust-lang/rust/issues/86442) to get
better error messages on IO errors
* [`const_option_ext`](https://github.com/rust-lang/rust/issues/91930) to have
static variables read from the environment that fall back to hard coded
defaults
Honestly, both of those are not really necessary or can be handled without
nightly. It's just that I'm using nightly anyway.

View File

@@ -2,14 +2,14 @@
## Installation ## Installation
Building GRM currently requires the nightly Rust toolchain. The easiest way is Building GRM requires the Rust toolchain to be installed. The easiest way is
using [`rustup`](https://rustup.rs/). Make sure that rustup is properly using [`rustup`](https://rustup.rs/). Make sure that rustup is properly
installed. installed.
Make sure that the nightly toolchain is installed: Make sure that the stable toolchain is installed:
``` ```
$ rustup toolchain install nightly $ rustup toolchain install stable
``` ```
Then, install the build dependencies: Then, install the build dependencies:
@@ -22,13 +22,13 @@ Then, install the build dependencies:
Then, it's a simple command to install the latest stable version: Then, it's a simple command to install the latest stable version:
```bash ```bash
$ cargo +nightly install git-repo-manager $ cargo install git-repo-manager
``` ```
If you're brave, you can also run the development build: If you're brave, you can also run the development build:
```bash ```bash
$ cargo +nightly install --git https://github.com/hakoerber/git-repo-manager.git --branch develop $ cargo install --git https://github.com/hakoerber/git-repo-manager.git --branch develop
``` ```
## Static build ## Static build
@@ -47,11 +47,11 @@ need `musl` and a few other build dependencies installed installed:
The, add the musl target via `rustup`: The, add the musl target via `rustup`:
``` ```
$ rustup +nightly target add x86_64-unknown-linux-musl $ rustup target add x86_64-unknown-linux-musl
``` ```
Then, use a modified build command to get a statically linked binary: Then, use a modified build command to get a statically linked binary:
``` ```
$ cargo +nightly install git-repo-manager --target x86_64-unknown-linux-musl --features=static-build $ cargo install git-repo-manager --target x86_64-unknown-linux-musl --features=static-build
``` ```

View File

@@ -163,7 +163,6 @@ def test_repos_find(configtype, exclude, default_format):
@pytest.mark.parametrize("configtype", ["toml", "yaml"]) @pytest.mark.parametrize("configtype", ["toml", "yaml"])
def test_repos_find_in_root(configtype, default_format): def test_repos_find_in_root(configtype, default_format):
with TempGitRepository() as repo_dir: with TempGitRepository() as repo_dir:
args = ["repos", "find", "local", repo_dir] args = ["repos", "find", "local", repo_dir]
if not default_format: if not default_format:
args += ["--format", configtype] args += ["--format", configtype]

View File

@@ -43,7 +43,9 @@ def test_repos_find_remote_invalid_provider(use_config):
assert cmd.returncode != 0 assert cmd.returncode != 0
assert len(cmd.stdout) == 0 assert len(cmd.stdout) == 0
if not use_config: if not use_config:
assert re.match(".*invalid value 'thisproviderdoesnotexist' for.*provider", cmd.stderr) assert re.match(
".*invalid value 'thisproviderdoesnotexist' for.*provider", cmd.stderr
)
@pytest.mark.parametrize("provider", PROVIDERS) @pytest.mark.parametrize("provider", PROVIDERS)

View File

@@ -312,7 +312,7 @@ def test_repos_sync_root_is_file(configtype):
cmd = grm(["repos", "sync", "config", "--config", config.name]) cmd = grm(["repos", "sync", "config", "--config", config.name])
assert cmd.returncode != 0 assert cmd.returncode != 0
assert "not a directory" in cmd.stderr.lower() assert "notadirectory" in cmd.stderr.lower()
@pytest.mark.parametrize("configtype", ["toml", "yaml"]) @pytest.mark.parametrize("configtype", ["toml", "yaml"])

View File

@@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "stable"
targets = ["x86_64-unknown-linux-musl"] targets = ["x86_64-unknown-linux-musl"]

View File

@@ -1,4 +1,3 @@
#![feature(io_error_more)]
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
use std::path::Path; use std::path::Path;

View File

@@ -313,7 +313,7 @@ pub trait Provider {
// about the data exchange format here. // about the data exchange format here.
repo.remove_namespace(); repo.remove_namespace();
ret.entry(namespace).or_insert(vec![]).push(repo); ret.entry(namespace).or_default().push(repo);
} }
Ok(ret) Ok(ret)

View File

@@ -4,6 +4,7 @@ use super::repo;
use comfy_table::{Cell, Table}; use comfy_table::{Cell, Table};
use std::fmt::Write;
use std::path::Path; use std::path::Path;
fn add_table_header(table: &mut Table) { fn add_table_header(table: &mut Table) {
@@ -56,9 +57,10 @@ fn add_repo_status(
repo_status repo_status
.branches .branches
.iter() .iter()
.map(|(branch_name, remote_branch)| { .fold(String::new(), |mut s, (branch_name, remote_branch)| {
format!( writeln!(
"branch: {}{}\n", &mut s,
"branch: {}{}",
&branch_name, &branch_name,
&match remote_branch { &match remote_branch {
None => String::from(" <!local>"), None => String::from(" <!local>"),
@@ -78,8 +80,9 @@ fn add_repo_status(
} }
} }
) )
.unwrap();
s
}) })
.collect::<String>()
.trim(), .trim(),
&match is_worktree { &match is_worktree {
true => String::from(""), true => String::from(""),
@@ -91,8 +94,10 @@ fn add_repo_status(
repo_status repo_status
.remotes .remotes
.iter() .iter()
.map(|r| format!("{}\n", r)) .fold(String::new(), |mut s, r| {
.collect::<String>() writeln!(&mut s, "{r}").unwrap();
s
})
.trim(), .trim(),
]); ]);

View File

@@ -128,8 +128,6 @@ pub fn find_repo_paths(path: &Path) -> Result<Vec<PathBuf>, String> {
"Failed to open \"{}\": {}", "Failed to open \"{}\": {}",
&path.display(), &path.display(),
match e.kind() { match e.kind() {
std::io::ErrorKind::NotADirectory =>
String::from("directory expected, but path is not a directory"),
std::io::ErrorKind::NotFound => String::from("not found"), std::io::ErrorKind::NotFound => String::from("not found"),
_ => format!("{:?}", e.kind()), _ => format!("{:?}", e.kind()),
} }
@@ -181,7 +179,7 @@ fn sync_repo(root_path: &Path, repo: &repo::Repo, init_worktree: bool) -> Result
"Repo already exists, but is not using a worktree setup", "Repo already exists, but is not using a worktree setup",
)); ));
}; };
} else if matches!(&repo.remotes, None) || repo.remotes.as_ref().unwrap().is_empty() { } else if repo.remotes.is_none() || repo.remotes.as_ref().unwrap().is_empty() {
print_repo_action( print_repo_action(
&repo.name, &repo.name,
"Repository does not have remotes configured, initializing new", "Repository does not have remotes configured, initializing new",