aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar lancebord 2026-03-03 11:53:15 -0500
committerGravatar lancebord 2026-03-03 11:53:15 -0500
commitc994411e27485866997f22c2cf1e84981ff7b7bb (patch)
tree56d59cbb47b383223524e10eccb0f98800fa529a
parentremove dependencies field (diff)
tagged and none update
-rw-r--r--src/action.rs49
-rw-r--r--src/config.rs2
-rw-r--r--src/util.rs53
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)?;