Harness the power of signify(1) to sign arbitrary git objects
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

list remote sigs

+92 -31
+86 -30
src/list_signatures.rs
··· 3 3 use std::collections::BTreeMap; 4 4 5 5 use anyhow::{Context, Result}; 6 - use git2::{Oid, Repository}; 6 + use git2::{Direction, Oid, ProxyOptions, Remote, Repository}; 7 7 8 8 use super::utils; 9 9 10 10 /// Execute the `list-signatures` command. 11 - pub fn command(output_json: bool) -> Result<()> { 11 + pub fn command(output_json: bool, remote: Option<String>) -> Result<()> { 12 12 let repo = utils::open_repository()?; 13 13 14 + if let Some(remote_name) = remote { 15 + let mut remote = repo 16 + .find_remote(&remote_name) 17 + .context("Unable to find remote")?; 18 + 19 + let proxy_options = { 20 + let mut opts = ProxyOptions::new(); 21 + opts.auto(); 22 + opts 23 + }; 24 + 25 + remote 26 + .connect_auth(Direction::Fetch, None, Some(proxy_options)) 27 + .with_context(|| { 28 + format!( 29 + "Failed to connect to remote {remote_name}, only \ 30 + remotes with no authentication are supported", 31 + ) 32 + })?; 33 + 34 + command_inner(&repo, output_json, &remote) 35 + } else { 36 + command_inner(&repo, output_json, &repo) 37 + } 38 + } 39 + 40 + fn command_inner<'repo, F: FindSigners + ?Sized>( 41 + repo: &'repo Repository, 42 + output_json: bool, 43 + find_signers: &'repo F, 44 + ) -> Result<()> { 14 45 if !output_json { 15 - output_signers_human(&repo) 46 + output_signers_human(repo, find_signers) 16 47 } else { 17 - output_signers_json(&repo) 48 + output_signers_json(repo, find_signers) 18 49 } 19 50 } 20 51 21 - fn output_signers_human(repo: &Repository) -> Result<()> { 22 - for (oid, signers) in find_signers(repo)? { 52 + fn output_signers_human<F: FindSigners + ?Sized>(repo: &Repository, f: &F) -> Result<()> { 53 + for (oid, signers) in f.find_signers()? { 23 54 let signed_rev = describe_object(repo, oid)?; 24 55 println!("Signers of {signed_rev}:"); 25 56 ··· 30 61 Ok(()) 31 62 } 32 63 33 - fn output_signers_json(repo: &Repository) -> Result<()> { 64 + fn output_signers_json<F: FindSigners + ?Sized>(repo: &Repository, f: &F) -> Result<()> { 34 65 fn print_signers(signers: Vec<Oid>) { 35 66 let mut signers_iter = signers.into_iter(); 36 67 ··· 44 75 print!("]"); 45 76 } 46 77 47 - let mut objs_iter = find_signers(repo)?.into_iter(); 78 + let mut objs_iter = f.find_signers()?.into_iter(); 48 79 49 80 print!("{{"); 50 81 if let Some((oid, signers)) = objs_iter.next() { ··· 83 114 .with_context(|| format!("Failed to format description of oid={oid}")) 84 115 } 85 116 86 - fn find_signers(repo: &Repository) -> Result<BTreeMap<Oid, Vec<Oid>>> { 87 - let mut signers: BTreeMap<_, Vec<_>> = BTreeMap::new(); 117 + trait FindSigners { 118 + fn find_signers(&self) -> Result<BTreeMap<Oid, Vec<Oid>>>; 119 + } 88 120 89 - for maybe_rev in repo 90 - .references_glob(utils::ALL_SIGNIFY_SIGNATURE_REFS) 91 - .context("Failed to look-up all git-signify signature refs")? 92 - { 93 - let rev = maybe_rev.context("Failed to parse git revision")?; 94 - let revname = rev.name().context("Invalid revision name")?; 121 + impl FindSigners for Repository { 122 + fn find_signers(&self) -> Result<BTreeMap<Oid, Vec<Oid>>> { 123 + let mut signers: BTreeMap<_, Vec<_>> = BTreeMap::new(); 95 124 96 - let Some(("", signer_and_oid)) = 97 - revname.split_once(utils::ALL_SIGNIFY_SIGNATURE_REFS_PREFIX) 98 - else { 99 - continue; 100 - }; 101 - let Some((signer, oid)) = signer_and_oid.split_once('/') else { 102 - continue; 103 - }; 125 + for maybe_rev in self 126 + .references_glob(utils::ALL_SIGNIFY_SIGNATURE_REFS) 127 + .context("Failed to look-up all git-signify signature refs")? 128 + { 129 + let rev = maybe_rev.context("Failed to parse git revision")?; 130 + let revname = rev.name().context("Invalid revision name")?; 131 + 132 + let Some((oid, signer)) = parse_signature_oid_and_signer(revname) else { 133 + continue; 134 + }; 104 135 105 - let oid = Oid::from_str(oid) 106 - .with_context(|| format!("Failed to parse git oid={oid} of signed obj"))?; 107 - let signer = Oid::from_str(signer) 108 - .with_context(|| format!("Failed to parse git signer with oid={oid}"))?; 136 + signers.entry(oid).or_default().push(signer); 137 + } 109 138 110 - signers.entry(oid).or_default().push(signer); 139 + Ok(signers) 111 140 } 141 + } 112 142 113 - Ok(signers) 143 + impl FindSigners for Remote<'_> { 144 + fn find_signers(&self) -> Result<BTreeMap<Oid, Vec<Oid>>> { 145 + let mut signers: BTreeMap<_, Vec<_>> = BTreeMap::new(); 146 + 147 + for (oid, signer) in self 148 + .list() 149 + .context("Failed to look-up remote refs")? 150 + .iter() 151 + .filter_map(|head| parse_signature_oid_and_signer(head.name())) 152 + { 153 + signers.entry(oid).or_default().push(signer); 154 + } 155 + 156 + Ok(signers) 157 + } 158 + } 159 + 160 + fn parse_signature_oid_and_signer(revname: &str) -> Option<(Oid, Oid)> { 161 + let ("", signer_and_oid) = revname.split_once(utils::ALL_SIGNIFY_SIGNATURE_REFS_PREFIX)? else { 162 + return None; 163 + }; 164 + let (signer, oid) = signer_and_oid.split_once('/')?; 165 + 166 + let oid = Oid::from_str(oid).ok()?; 167 + let signer = Oid::from_str(signer).ok()?; 168 + 169 + Some((oid, signer)) 114 170 }
+6 -1
src/main.rs
··· 72 72 /// Output JSON 73 73 #[arg(long)] 74 74 json: bool, 75 + 76 + /// The name of the remote repository, to 77 + /// list remote signatures 78 + #[arg(short = 'R', long)] 79 + remote: Option<String>, 75 80 }, 76 81 /// Look-up a signature revision 77 82 RevLookup { ··· 162 167 } => verify::command(public_key, rev), 163 168 Action::Push { remote } => push::command(&remote.unwrap_or(Cow::Borrowed("origin"))), 164 169 Action::Pull { remote } => pull::command(&remote.unwrap_or(Cow::Borrowed("origin"))), 165 - Action::ListSignatures { json } => list_signatures::command(json), 170 + Action::ListSignatures { json, remote } => list_signatures::command(json, remote), 166 171 Action::RevLookup { 167 172 public_key, 168 173 git_rev: rev,