diff options
| author | 2026-03-03 11:53:15 -0500 | |
|---|---|---|
| committer | 2026-03-03 11:53:15 -0500 | |
| commit | c994411e27485866997f22c2cf1e84981ff7b7bb (patch) | |
| tree | 56d59cbb47b383223524e10eccb0f98800fa529a /src | |
| parent | remove dependencies field (diff) | |
tagged and none update
Diffstat (limited to 'src')
| -rw-r--r-- | src/action.rs | 49 | ||||
| -rw-r--r-- | src/config.rs | 2 | ||||
| -rw-r--r-- | src/util.rs | 53 |
3 files changed, 91 insertions, 13 deletions
diff --git a/src/action.rs b/src/action.rs index 8a9b4b5..dba937e 100644 --- a/src/action.rs +++ b/src/action.rs @@ -137,18 +137,43 @@ fn update() -> Result<(), String> { let mut update_pkgs: PackageList = vec![]; let mut lockfile = Lockfile::new(); for (name, path, config_path) in package_paths { - util::pull_repo(&path).map_err(|e| format!("failed to update repo: {e}"))?; - let oid = util::get_commit_hash_full(&path) - .map_err(|e| format!("could not get commit hash: {e}"))?; - let url = util::get_remote_url(&path) - .map_err(|e| format!("failed to get url for remote origin: {e}"))?; - let p = Package { - name: name.clone(), - source: url, - checksum: oid.to_string(), - }; - if lockfile.out_of_date(p) { - update_pkgs.push((name, path, config_path)); + let config = Config::new(&config_path).ok_or("config not found".to_string())?; + if let Some(u) = config.update { + match u.as_str() { + "live" => { + util::pull_repo(&path).map_err(|e| format!("failed to update repo: {e}"))?; + let oid = util::get_commit_hash_full(&path) + .map_err(|e| format!("could not get commit hash: {e}"))?; + let url = util::get_remote_url(&path) + .map_err(|e| format!("failed to get url for remote origin: {e}"))?; + let p = Package { + name: name.clone(), + source: url, + checksum: oid.to_string(), + }; + if lockfile.out_of_date(p) { + update_pkgs.push((name, path, config_path)); + } + } + "tagged" => { + util::pull_latest_tag(&path) + .map_err(|e| format!("failed to update repo: {e}"))?; + let oid = util::get_commit_hash_full(&path) + .map_err(|e| format!("could not get commit hash: {e}"))?; + let url = util::get_remote_url(&path) + .map_err(|e| format!("failed to get url for remote origin: {e}"))?; + let p = Package { + name: name.clone(), + source: url, + checksum: oid.to_string(), + }; + if lockfile.out_of_date(p) { + update_pkgs.push((name, path, config_path)); + } + } + "none" => continue, + e => return Err(format!("unknown update mode {e}")), + } } } diff --git a/src/config.rs b/src/config.rs index 0339739..af5b084 100644 --- a/src/config.rs +++ b/src/config.rs @@ -80,7 +80,7 @@ pub fn create_config(package: &str) -> Result<(), String> { let template = format!( r#"# {package} configuration -update = "live" # no | live | tagged +update = "live" # none | live | tagged [hooks] build = "make" diff --git a/src/util.rs b/src/util.rs index a829327..5394fb0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -130,6 +130,59 @@ pub fn print_collected_packages(packages: &PackageList, message: &str) { ); } +pub fn pull_latest_tag(path: &Path) -> Result<(), git2::Error> { + let repo = Repository::open(path)?; + + let head = repo.head()?; + let branch = head + .shorthand() + .ok_or_else(|| git2::Error::from_str("Could not determine current branch"))? + .to_string(); + + let mut callbacks = RemoteCallbacks::new(); + callbacks.credentials(|_url, username_from_url, _allowed| { + Cred::ssh_key_from_agent(username_from_url.unwrap()) + }); + + let mut fetch_options = FetchOptions::new(); + fetch_options.remote_callbacks(callbacks); + + let mut remote = repo.find_remote("origin")?; + remote.fetch(&["refs/tags/*:refs/tags/*"], Some(&mut fetch_options), None)?; + + let tag_names = repo.tag_names(None)?; + + let mut latest_commit = None; + let mut latest_time = 0; + + for name in tag_names.iter().flatten() { + let obj = repo.revparse_single(&format!("refs/tags/{}", name))?; + let commit = obj.peel_to_commit()?; + + let time = commit.time().seconds(); + if time > latest_time { + latest_time = time; + latest_commit = Some(commit); + } + } + + let latest_commit = latest_commit.ok_or_else(|| git2::Error::from_str("No tags found"))?; + + let annotated = repo.find_annotated_commit(latest_commit.id())?; + let (analysis, _) = repo.merge_analysis(&[&annotated])?; + + if analysis.is_fast_forward() { + let refname = format!("refs/heads/{}", branch); + let mut reference = repo.find_reference(&refname)?; + reference.set_target(latest_commit.id(), "Fast-Forward to latest tag")?; + repo.set_head(&refname)?; + repo.checkout_head(Some(CheckoutBuilder::default().force()))?; + } else if !analysis.is_up_to_date() { + println!("Cannot fast-forward to latest tag."); + } + + Ok(()) +} pub fn pull_repo(path: &Path) -> Result<(), git2::Error> { let repo = Repository::open(path)?; |
