Skip to content

Commit 6cc111f

Browse files
committed
only valid full & partial SHAs accepted
1 parent 898af8a commit 6cc111f

1 file changed

Lines changed: 49 additions & 31 deletions

File tree

src/commands/releases/set_commits.rs

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clap::{Arg, ArgAction, ArgMatches, Command};
55
use lazy_static::lazy_static;
66
use regex::Regex;
77

8-
use crate::api::{Api, NewRelease, NoneReleaseInfo, OptionalReleaseInfo, UpdatedRelease};
8+
use crate::api::{Api, NewRelease, NoneReleaseInfo, OptionalReleaseInfo, Ref, UpdatedRelease};
99
use crate::config::Config;
1010
use crate::utils::args::ArgExt as _;
1111
use crate::utils::formatting::Table;
@@ -55,17 +55,13 @@ pub fn make_command(command: Command) -> Command {
5555
.action(ArgAction::Append)
5656
.help("Defines a single commit for a repo as \
5757
identified by the repo name in the remote Sentry config. \
58-
If no commit has been specified sentry-cli will attempt \
59-
to auto discover that repository in the local git repo \
60-
and then use the HEAD commit. This will either use the \
61-
current git repository or attempt to auto discover a \
62-
submodule with a compatible URL.\n\n\
63-
The value can be provided as `REPO` in which case sentry-cli \
64-
will auto-discover the commit based on reachable repositories. \
65-
Alternatively it can be provided as `REPO#PATH` in which case \
66-
the current commit of the repository at the given PATH is \
67-
assumed. To override the revision `@REV` can be appended \
68-
which will force the revision to a certain value."))
58+
The value must be provided as `REPO@SHA` where SHA is a \
59+
Git commit SHA (full 40-character or partial 4+ characters). \
60+
To specify a range, use `REPO@PREV_SHA..SHA` format.\n\n\
61+
Examples:\n\
62+
- `my-repo@abc123` (partial SHA)\n\
63+
- `my-repo@abc123def456789...` (full SHA)\n\
64+
- `my-repo@abc123..def456` (commit range)"))
6965
// Legacy flag that has no effect, left hidden for backward compatibility
7066
.arg(Arg::new("ignore-empty")
7167
.long("ignore-empty")
@@ -83,14 +79,22 @@ fn strip_sha(sha: &str) -> &str {
8379
sha
8480
}
8581
}
82+
83+
/// Validates that a string is a valid Git SHA (full or partial)
84+
fn is_valid_sha(sha: &str) -> bool {
85+
lazy_static! {
86+
static ref SHA_RE: Regex = Regex::new(r"^[a-fA-F0-9]{4,40}$").unwrap();
87+
}
88+
SHA_RE.is_match(sha)
89+
}
90+
8691
pub fn execute(matches: &ArgMatches) -> Result<()> {
8792
let config = Config::current();
8893
let api = Api::current();
8994
let authenticated_api = api.authenticated()?;
9095
let version = matches.get_one::<String>("version").unwrap();
9196
let org = config.get_org(matches)?;
9297
let repos = authenticated_api.list_organization_repos(&org)?;
93-
let mut commit_specs = vec![];
9498

9599
let heads = if repos.is_empty() {
96100
None
@@ -105,30 +109,44 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
105109
Some(vec![])
106110
} else if matches.get_flag("local") {
107111
None
108-
} else {
109-
if let Some(commits) = matches.get_many::<String>("commits") {
110-
for spec in commits {
111-
let commit_spec = CommitSpec::parse(spec)?;
112-
if repos
113-
.iter()
114-
.any(|r| r.name.to_lowercase() == commit_spec.repo.to_lowercase())
115-
{
116-
commit_specs.push(commit_spec);
117-
} else {
118-
bail!("Unknown repo '{}'", commit_spec.repo);
112+
} else if let Some(commits) = matches.get_many::<String>("commits") {
113+
let mut refs = vec![];
114+
for spec in commits {
115+
let commit_spec = CommitSpec::parse(spec)?;
116+
117+
if !repos
118+
.iter()
119+
.any(|r| r.name.to_lowercase() == commit_spec.repo.to_lowercase())
120+
{
121+
bail!("Unknown repo '{}'", commit_spec.repo);
122+
}
123+
124+
if !is_valid_sha(&commit_spec.rev) {
125+
bail!(
126+
"Invalid commit SHA '{}'. Only Git SHAs (full or partial) are supported.",
127+
commit_spec.rev
128+
);
129+
}
130+
131+
if let Some(ref prev_rev) = commit_spec.prev_rev {
132+
if !is_valid_sha(prev_rev) {
133+
bail!("Invalid previous commit SHA '{}'. Only Git SHAs (full or partial) are supported.", prev_rev);
119134
}
120135
}
136+
137+
refs.push(Ref {
138+
repo: commit_spec.repo,
139+
rev: commit_spec.rev,
140+
prev_rev: commit_spec.prev_rev,
141+
});
121142
}
122-
let commits = find_heads(
123-
Some(commit_specs),
124-
&repos,
125-
Some(config.get_cached_vcs_remote()),
126-
)?;
127-
if commits.is_empty() {
143+
if refs.is_empty() {
128144
None
129145
} else {
130-
Some(commits)
146+
Some(refs)
131147
}
148+
} else {
149+
None
132150
};
133151

134152
// make sure the release exists if projects are given

0 commit comments

Comments
 (0)