Skip to content

Commit

Permalink
refactor: improve configuration parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
easbarba committed Sep 1, 2023
1 parent 1e74d04 commit dc8d6bb
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 60 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
-->

## 0.3.0

- refactor: improve configuration parsing

## 0.2.0

- feat: implement cli interface
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "onur"
version = "0.2.0"
version = "0.3.0"
edition = "2021"
description = "Easily manage multiple FLOSS repositories"
authors = ["EAS Barbosa <easbarba@outlook.com>"]
Expand Down
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,18 @@ lint:
pub:
cargo publish

install: build
cp ./target/release/onur ${HOME}/.local/bin/

# -------------------------------- COMMANDS

grab:
cargo run -- grab --verbose
cargo run -- --verbose grab

backup:
cargo run -- backup --name nuxt,awesomewm --verbose
cargo run -- --verbose backup --name nuxt,awesomewm

make help:
cargo run

.PHONY: deps test fmt lint pub run build grab archive image-build image-clean image-test
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Easily manage multiple FLOSS repositories.

# Installation

[java](https://gitlab.com/easbarba/onur-java) | [python](https://gitlab.com/easbarba/onur) | [php](https://gitlab.com/easbarba/onur-php) | [ruby](https://gitlab.com/easbarba/qas-rb) | [go](https://gitlab.com/easbarba/qas-go)
[go](https://gitlab.com/easbarba/onur-go) | [java](https://gitlab.com/easbarba/onur-java) | [python](https://gitlab.com/easbarba/onur-python) | [php](https://gitlab.com/easbarba/onur-php) | [ruby](https://gitlab.com/easbarba/onur-ruby)

## Usage

Expand Down Expand Up @@ -59,6 +59,14 @@ More examples of configuration files are at `examples`.

## Settings

A TOML settings file may define the behavior of `onur`:

```toml
single-branch = true
quiet = true
depth = 1
```

## Options

Consult `onur --help` for more options.
Expand Down
9 changes: 6 additions & 3 deletions src/actions/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@

use std::path::PathBuf;

use git2::Repository;
use git2::build;

pub fn run(project: &crate::domain::project::Project, path: PathBuf) {
match Repository::clone(&project.url, path) {
pub fn run(project: &crate::domain::project::Project, path: PathBuf, _verbose: bool) {
let mut bu = build::RepoBuilder::new();
bu.branch(&project.branch);

match bu.clone(&project.url, &path) {
Ok(repo) => repo,
Err(e) => panic!("failed to clone: {}", e),
};
Expand Down
102 changes: 74 additions & 28 deletions src/actions/pull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
use std::path::PathBuf;

use git2::Repository;
use std::io::{self, Write};

use crate::domain::project::Project;

pub fn run(project: &Project, path: PathBuf) -> Result<(), git2::Error> {
pub fn run(project: &Project, path: PathBuf, _verbose: bool) -> Result<(), git2::Error> {
let repo = Repository::open(path)?;
let mut remote = repo.find_remote("origin")?;
let fetch_commit = do_fetch(&repo, &[&project.branch], &mut remote)?;
Expand All @@ -33,20 +34,85 @@ fn do_fetch<'a>(
refs: &[&str],
remote: &'a mut git2::Remote,
) -> Result<git2::AnnotatedCommit<'a>, git2::Error> {
let cb = git2::RemoteCallbacks::new();
let mut cb = git2::RemoteCallbacks::new();

// Print out our transfer progress.
cb.transfer_progress(|_| {
// if stats.received_objects() == stats.total_objects() {
// print!(
// "Resolving deltas {}/{}\r",
// stats.indexed_deltas(),
// stats.total_deltas()
// );
// } else if stats.total_objects() > 0 {
// print!(
// "Received {}/{} objects ({}) in {} bytes\r",
// stats.received_objects(),
// stats.total_objects(),
// stats.indexed_objects(),
// stats.received_bytes()
// );
// }
io::stdout().flush().unwrap();
true
});

let mut fo = git2::FetchOptions::new();
fo.remote_callbacks(cb);
// Always fetch all tags.
// Perform a download and also update tips
fo.download_tags(git2::AutotagOption::All);

// println!("Fetching {} for repo", remote.name().unwrap());
remote.fetch(refs, Some(&mut fo), None)?;

// If there are local objects (we got a thin pack), then tell the user
// how many objects we saved from having to cross the network.
// let stats = remote.stats();
// if stats.local_objects() > 0 {
// println!(
// "\rReceived {}/{} objects in {} bytes (used {} local \
// objects)",
// stats.indexed_objects(),
// stats.total_objects(),
// stats.received_bytes(),
// stats.local_objects()
// );
// } else {
// println!(
// "\rReceived {}/{} objects in {} bytes",
// stats.indexed_objects(),
// stats.total_objects(),
// stats.received_bytes()
// );
// }

let fetch_head = repo.find_reference("FETCH_HEAD")?;
Ok(repo.reference_to_annotated_commit(&fetch_head)?)
}

fn fast_forward(
repo: &Repository,
lb: &mut git2::Reference,
rc: &git2::AnnotatedCommit,
) -> Result<(), git2::Error> {
let name = match lb.name() {
Some(s) => s.to_string(),
None => String::from_utf8_lossy(lb.name_bytes()).to_string(),
};
let msg = format!("Fast-Forward: Setting {} to id: {}", name, rc.id());
// println!("{}", msg);
lb.set_target(rc.id(), &msg)?;
repo.set_head(&name)?;
repo.checkout_head(Some(
git2::build::CheckoutBuilder::default()
// For some reason the force is required to make the working directory actually get updated
// I suspect we should be adding some logic to handle dirty working directory states
// but this is just an example so maybe not.
.force(),
))?;
Ok(())
}

fn normal_merge(
repo: &Repository,
local: &git2::AnnotatedCommit,
Expand All @@ -60,7 +126,7 @@ fn normal_merge(
let mut idx = repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?;

if idx.has_conflicts() {
println!("Merge conflicts detected...");
// println!("Merge conflicts detected...");
repo.checkout_index(Some(&mut idx), None)?;
return Ok(());
}
Expand Down Expand Up @@ -94,7 +160,7 @@ fn do_merge<'a>(

// 2. Do the appropriate merge
if analysis.0.is_fast_forward() {
println!("Doing a fast forward");
// println!("Doing a fast forward");
// do a fast forward
let refname = format!("refs/heads/{}", remote_branch);
match repo.find_reference(&refname) {
Expand Down Expand Up @@ -126,28 +192,8 @@ fn do_merge<'a>(
normal_merge(&repo, &head_commit, &fetch_commit)?;
}

Ok(())
}

fn fast_forward(
repo: &Repository,
lb: &mut git2::Reference,
rc: &git2::AnnotatedCommit,
) -> Result<(), git2::Error> {
let name = match lb.name() {
Some(s) => s.to_string(),
None => String::from_utf8_lossy(lb.name_bytes()).to_string(),
};
let msg = format!("Fast-Forward: Setting {} to id: {}", name, rc.id());
println!("{}", msg);
lb.set_target(rc.id(), &msg)?;
repo.set_head(&name)?;
repo.checkout_head(Some(
git2::build::CheckoutBuilder::default()
// For some reason the force is required to make the working directory actually get updated
// I suspect we should be adding some logic to handle dirty working directory states
// but this is just an example so maybe not.
.force(),
))?;
// else {
// println!("Nothing to do...");
// }
Ok(())
}
14 changes: 7 additions & 7 deletions src/commands/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ use crate::{

pub fn run(verbose: bool) {
parser::all(true).into_iter().for_each(|config| {
println!("Topic: {:?}", &config.0);
config.1.into_iter().for_each(|projekt| {
print_info(&projekt, verbose);
println!("Topic: {:?}", &config.topic);
config.projects.into_iter().for_each(|project| {
print_info(&project, verbose);

let filepath = projects_home().join(&config.0).join(&projekt.name);
let filepath = projects_home().join(&config.topic).join(&project.name);
if filepath.exists() {
match pull::run(&projekt, filepath) {
match pull::run(&project, filepath, verbose) {
Err(_) => (), //println!("{:?}", e),
_ => (),
}
} else {
clone::run(&projekt, filepath);
clone::run(&project, filepath, verbose);
}
});

println!()
println!();
});
}

Expand Down
7 changes: 5 additions & 2 deletions src/database/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ pub fn exist() -> bool {
pub fn empty() -> bool {
globals::config_home()
.read_dir()
.expect("meh")
.expect("No configuration folder found")
.next()
.is_none()
}

pub fn count() -> usize {
globals::config_home().read_dir().expect("foool").count()
globals::config_home()
.read_dir()
.expect("No configuration folder found")
.count()
}

// list all configurations file names
Expand Down
18 changes: 10 additions & 8 deletions src/database/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,24 @@
* limitations under the License.
*/

use std::{collections::HashMap, fs};
use std::{fs, path};

use crate::database::files;
use crate::domain::config::Config;
use crate::domain::project::Project;

// Parse one configuration
fn one(f: std::path::PathBuf) -> Vec<Project> {
let file = fs::read_to_string(f.as_path()).expect("gimme it");
let result: Vec<Project> = serde_json::from_str(&file).expect("translate it");
fn one(filepath: path::PathBuf) -> Config {
let file = fs::read_to_string(filepath.as_path()).expect("gimme it");
let topic = filepath.file_stem().unwrap().to_str().unwrap().to_string();
let projects: Vec<Project> = serde_json::from_str(&file).expect("translate it");

result
Config::new(topic, projects)
}

// Collect all parsed configurations
pub fn all(verbose: bool) -> HashMap<String, Vec<Project>> {
let mut configs: HashMap<String, Vec<Project>> = HashMap::new();
pub fn all(verbose: bool) -> Vec<Config> {
let mut configs: Vec<Config> = Vec::new();

if verbose {
print_info();
Expand All @@ -39,7 +41,7 @@ pub fn all(verbose: bool) -> HashMap<String, Vec<Project>> {
.unwrap()
.into_iter()
.for_each(|f| {
configs.insert(f.file_stem().unwrap().to_str().unwrap().to_string(), one(f));
configs.push(one(f.to_path_buf()));
});

return configs;
Expand Down
2 changes: 1 addition & 1 deletion src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
* limitations under the License.
*/

pub mod configuration;
pub mod config;
pub mod project;
13 changes: 13 additions & 0 deletions src/domain/configuration.rs → src/domain/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use super::project::Project;

pub struct Config {
pub topic: String,
pub projects: Vec<Project>,
}

impl Config {
pub fn new(topic: String, projects: Vec<Project>) -> Config {
Config { topic, projects }
}
}
9 changes: 8 additions & 1 deletion src/misc/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@
* limitations under the License.
*/

use clap::{arg, Command};
use clap::{arg, Arg, ArgAction, Command};

pub fn options() -> Command {
Command::new("onur")
.about("Easily manage multiple FLOSS repositories.")
.arg(
Arg::new("verbose")
.help("get as much info as possible")
.short('v')
.long("verbose")
.action(ArgAction::SetTrue),
)
.subcommand_required(true)
.arg_required_else_help(true)
.allow_external_subcommands(true)
Expand Down
12 changes: 6 additions & 6 deletions src/misc/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@

use std::path::{Path, PathBuf};

// user's home
/// user's home directory
pub fn user_home() -> &'static Path {
Path::new(env!("HOME"))
Path::new(env!("HOME", "User home directory not found!"))
}

// user's home
/// user's projects directory
pub fn projects_home() -> PathBuf {
Path::new(env!("HOME")).join("Projects")
user_home().join("Projects")
}

// project main config folder
/// main config directory
pub fn config_home() -> PathBuf {
Path::new(user_home()).join(".config").join("onur")
user_home().join(".config").join("onur")
}

0 comments on commit dc8d6bb

Please sign in to comment.