diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..68c6505 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,77 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [0.0.7] - 2023-07-02 + +### Bug Fixes + +- Changed config.yaml location +- Increased scope of push field +- Remove potentially destructive operaton +- Fixed mini-license typos +- Fixed testing with hashmap arch +- Spinner on all repoactions +- Fixed commit in quick +- [**breaking**] Fixed quick, fast messages +- Fixed commit with editor regression + +### Documentation + +- Architectural Overview +- Moved charts to doc/img +- Update image locations +- Moved ARCHITECTURE.md to doc/ +- Added some documentation +- Added roadmap +- Added git cliff config + +### Features + +- Started flakification +- Added nix flake #5 +- [**breaking**] Add push field +- [**breaking**] Add repo flags +- [**breaking**] Implemented naive categories +- Started work on using spinners +- Added pull flag +- React to exit code of git +- Started adding multi instruction logic +- Added fast subcommand +- Add Commit, Add flags +- [**breaking**] Added Quick, Fast flags +- Made category flags optional +- Made categories.repo optional +- Made repo flags optional + +### Miscellaneous Tasks + +- Version bump to v0.0.3 +- Moved install scripts to ./bin +- Merge 0.0.6 +- Bump to 0.0.7 + +### Refactor + +- Fixed various clippy errors +- Removed unused code from flake +- Improved GitRepo assoc. function debug +- Removed redundant line in Cargo.toml +- Created on_all for config struct +- Naive nested hashmap +- Generic refactor + +### Security + +- Removed atty dependency +- Removed atty dependency + +### Testing + +- Removed unused ./test dir + +### WIP + +- Mvp flake working + + diff --git a/Cargo.toml b/Cargo.toml index 4536876..6212798 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "gg" -version = "0.0.6" +version = "0.0.7" edition = "2021" -authors = ["Christina Sørensen "] +authors = ["Christina Sørensen"] repository = "https://github.com/cafkafk/gg" license = "GPL-3.0-only" diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..0a88218 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,75 @@ +# git-cliff ~ default configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://tera.netlify.app/docs +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# remove the leading and trailing whitespace from the template +trim = true +# changelog footer +footer = """ + +""" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))"}, # replace issue numbers +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^doc", group = "Documentation" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactor" }, + { message = "^style", group = "Styling" }, + { message = "^test", group = "Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore", group = "Miscellaneous Tasks" }, + { body = ".*security", group = "Security" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" +# regex for ignoring tags +ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" +# limit the number of commits included in the changelog. +# limit_commits = 42 diff --git a/doc/roadmap.org b/doc/roadmap.org index 8b6665a..438ad75 100644 --- a/doc/roadmap.org +++ b/doc/roadmap.org @@ -5,11 +5,11 @@ - [ ] Generic repositories - [ ] Version pinning - [ ] libgit2 (maybe) -* 0.1.0 [20%] [1/5] +* 0.1.0 [60%] [3/5] - [X] No functionality regressions - [X] commit works in quick, fast - [X] commit with edit works -- [ ] Repo Flags Finished +- [X] Repo Flags Finished - [ ] Category Flags Finished -- [ ] Optional Fields +- [X] Optional Fields - [ ] Subcommands diff --git a/src/git.rs b/src/git.rs index 4bb0e65..53e093c 100644 --- a/src/git.rs +++ b/src/git.rs @@ -28,12 +28,24 @@ use std::{fs, process::Command}; /// An enum containing flags that change behaviour of repos and categories #[derive(PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, Debug)] pub enum RepoFlags { - /// If push is set, the repository should respond to the push subcommand - Push, /// If clone is set, the repository should respond to the clone subcommand Clone, /// If pull is set, the repository should respond to the pull subcommand Pull, + /// If add is set, the repository should respond to the add subcommand + Add, + /// If commit is set, the repository should respond to the commit subcommand + Commit, + /// If push is set, the repository should respond to the push subcommand + Push, + /// If push is set, the repository should respond to the Qucik subcommand + /// + /// This is a shortcut for Add, Commit, Push + Quick, + /// If push is set, the repository should respond to the Fast and Qucik subcommand + /// + /// This is a shortcut for Pull, Add, Commit, Push + Fast, } /// Represents the config.toml file. @@ -56,11 +68,13 @@ pub struct Config { /// This allows you to organize your repositories into categories #[derive(PartialEq, Debug, Serialize, Deserialize)] pub struct Category { - pub flags: Vec, // FIXME: not implemented + #[serde(skip_serializing_if = "Option::is_none")] + pub flags: Option>, // FIXME: not implemented /// map of all categories /// /// Key should conceptually be seen as the name of the category. - pub repos: HashMap, + #[serde(skip_serializing_if = "Option::is_none")] + pub repos: Option>, } /// Contain fields for a single link. @@ -78,7 +92,8 @@ pub struct GitRepo { pub name: String, pub path: String, pub url: String, - pub flags: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub flags: Option>, } //////////////////////////////////// @@ -143,7 +158,12 @@ impl Links { impl GitRepo { /// Clones the repository to its specified folder. fn clone(&self) -> bool { - if self.flags.contains(&RepoFlags::Clone) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .contains(&RepoFlags::Clone) + { // TODO: check if &self.name already exists in dir let output = Command::new("git") .current_dir(&self.path) @@ -160,7 +180,13 @@ impl GitRepo { } /// Pulls the repository if able. fn pull(&self) -> bool { - if self.flags.contains(&RepoFlags::Pull) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .iter() + .any(|s| s == &RepoFlags::Pull || s == &RepoFlags::Fast) + { let output = Command::new("git") .current_dir(format!("{}{}", &self.path, &self.name)) .arg("pull") @@ -174,7 +200,13 @@ impl GitRepo { } /// Adds all files in the repository. fn add_all(&self) -> bool { - if self.flags.contains(&RepoFlags::Push) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .iter() + .any(|s| s == &RepoFlags::Add || s == &RepoFlags::Quick || s == &RepoFlags::Fast) + { let output = Command::new("git") .current_dir(format!("{}{}", &self.path, &self.name)) .arg("add") @@ -196,7 +228,13 @@ impl GitRepo { /// easy #[allow(dead_code)] fn commit(&self) -> bool { - if self.flags.contains(&RepoFlags::Push) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .iter() + .any(|s| s == &RepoFlags::Commit || s == &RepoFlags::Quick || s == &RepoFlags::Fast) + { let status = Command::new("git") .current_dir(format!("{}{}", &self.path, &self.name)) .arg("commit") @@ -210,7 +248,13 @@ impl GitRepo { } /// Tries to commit changes with a message argument. fn commit_with_msg(&self, msg: &str) -> bool { - if self.flags.contains(&RepoFlags::Push) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .iter() + .any(|s| s == &RepoFlags::Commit || s == &RepoFlags::Quick || s == &RepoFlags::Fast) + { let output = Command::new("git") .current_dir(format!("{}{}", &self.path, &self.name)) .arg("commit") @@ -226,7 +270,13 @@ impl GitRepo { } /// Attempts to push the repository. fn push(&self) -> bool { - if self.flags.contains(&RepoFlags::Push) { + if self + .flags + .as_ref() + .expect("failed to unwrap flags") + .iter() + .any(|s| s == &RepoFlags::Push || s == &RepoFlags::Quick || s == &RepoFlags::Fast) + { let output = Command::new("git") .current_dir(format!("{}{}", &self.path, &self.name)) .arg("push") @@ -278,7 +328,7 @@ impl Config { F: Fn(&GitRepo), { for (_, category) in self.categories.iter() { - for (_, repo) in category.repos.iter() { + for (_, repo) in category.repos.as_ref().expect("failed to get repos").iter() { f(repo); } } @@ -293,7 +343,7 @@ impl Config { F: Fn(&GitRepo) -> bool, { for (_, category) in self.categories.iter() { - for (_, repo) in category.repos.iter() { + for (_, repo) in category.repos.as_ref().expect("failed to get repos").iter() { let mut sp = Spinner::new(Spinners::Dots10, format!("{}: {}", repo.name, op).into()); if f(repo) { @@ -347,7 +397,7 @@ impl Config { /// ``` pub fn series_on_all(&self, closures: Vec) { for (_, category) in self.categories.iter() { - for (_, repo) in category.repos.iter() { + for (_, repo) in category.repos.as_ref().expect("failed to get repos").iter() { for instruction in closures.iter() { let f = &instruction.closure; let op = instruction.operation; @@ -394,7 +444,7 @@ impl Config { /// ``` pub fn all_on_all(&self, closures: Vec) { for (_, category) in self.categories.iter() { - for (_, repo) in category.repos.iter() { + for (_, repo) in category.repos.as_ref().expect("failed to get repos").iter() { for instruction in closures.iter() { let f = &instruction.closure; let op = instruction.operation; diff --git a/src/main.rs b/src/main.rs index 68d6816..6012201 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,8 +126,8 @@ mod config { #[test] fn init_config_populate() { let default_category = Category { - flags: vec![], - repos: HashMap::new(), + flags: Some(vec![]), + repos: Some(HashMap::new()), }; let mut config = Config { categories: HashMap::new(), @@ -142,13 +142,15 @@ mod config { .get_mut(&format!("{}", 0).to_string()) .expect("category not found") .repos + .as_mut() + .expect("failed to get repo") .insert( format!("{}", i).to_string(), GitRepo { name: "test repo".to_string(), path: "/tmp".to_string(), url: "https://github.com/cafkafk/gg".to_string(), - flags: vec![Clone, Push], + flags: Some(vec![Clone, Push]), }, ); } @@ -196,6 +198,8 @@ mod config { .get(cat_name) .expect("failed to get category") .repos + .as_ref() + .expect("failed to get repo") .get(repo_name) .expect("failed to get category")) } diff --git a/src/test/config.yaml b/src/test/config.yaml index c53665b..54dcaac 100644 --- a/src/test/config.yaml +++ b/src/test/config.yaml @@ -13,7 +13,6 @@ categories: url: https://github.com/starship/starship.git flags: [Clone, Push] utils: - flags: [] repos: gg: name: gg @@ -25,6 +24,18 @@ categories: path: /home/ces/org/src/git/ url: git@github.com:cafkafk/li.git flags: [Clone, Push] + empty: + stuff: + flags: [] + repos: + gg: + name: gg + path: /home/ces/.dots/ + url: git@github.com:cafkafk/gg.git + li: + name: li + path: /home/ces/org/src/git/ + url: git@github.com:cafkafk/li.git links: - name: gg rx: /home/ces/.config/gg diff --git a/src/test/test.yaml b/src/test/test.yaml index ca79c57..b5b3327 100644 --- a/src/test/test.yaml +++ b/src/test/test.yaml @@ -1,6 +1,5 @@ categories: utils: - flags: [] repos: li: name: li @@ -16,6 +15,17 @@ categories: flags: - Clone - Push + stuff: + flags: [] + repos: + li: + name: li + path: /home/ces/org/src/git/ + url: git@github.com:cafkafk/li.git + gg: + name: gg + path: /home/ces/.dots/ + url: git@github.com:cafkafk/gg.git config: flags: [] repos: @@ -33,6 +43,7 @@ categories: flags: - Clone - Push + empty: {} links: - name: gg rx: /home/ces/.config/gg