1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
//! ref: composer/src/Composer/Package/Version/VersionBumper.php
use crate::package::PackageInterface;
use crate::package::dumper::ArrayDumper;
use crate::package::loader::ArrayLoader;
use crate::package::version::VersionParser;
use crate::util::Platform;
use anyhow::Result;
use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::intervals::Intervals;
#[derive(Debug)]
pub struct VersionBumper;
impl VersionBumper {
pub fn bump_requirement(
&self,
constraint: &AnyConstraint,
package: &dyn PackageInterface,
) -> Result<String> {
let parser = VersionParser::new();
let pretty_constraint = constraint.get_pretty_string();
if pretty_constraint.starts_with("dev-") {
return Ok(pretty_constraint);
}
let mut version = package.get_version().to_string();
if version.starts_with("dev-") {
// TODO(phase-b): ArrayLoader::new takes Option<VersionParser> by value; pass None until
// VersionParser sharing is reconciled.
let _ = &parser;
let loader = ArrayLoader::new(None, false);
let dumper = ArrayDumper::new();
let dumped = dumper.dump(package);
let extra = loader.get_branch_alias(&dumped)?;
if extra.is_none() || extra.as_deref() == Some(VersionParser::DEFAULT_BRANCH_ALIAS) {
return Ok(pretty_constraint);
}
version = extra.unwrap();
}
let intervals = Intervals::get(constraint)?;
if !intervals.branches.names.is_empty() {
return Ok(pretty_constraint);
}
let major = Preg::replace(r"{^([1-9][0-9]*|0\.\d+).*}", "$1", &version)?;
let version_without_suffix =
Preg::replace(r"{(?:\.(?:0|9999999))+(-dev)?$}", "", &version)?;
let new_pretty_constraint = format!("^{}", version_without_suffix);
if !Preg::is_match(r"{^\^\d+(\.\d+)*$}", &new_pretty_constraint)? {
return Ok(pretty_constraint);
}
let pattern = format!(
r#"{{
(?<=,|\ |\||^) # leading separator
(?P<constraint>
\^v?{major}(?:\.\d+)* # e.g. ^2.anything
| ~v?{major}(?:\.\d+){{1,3}} # e.g. ~2.2 or ~2.2.2 or ~2.2.2.2
| v?{major}(?:\.[*x])+ # e.g. 2.* or 2.*.* or 2.x.x.x etc
| >=v?\d(?:\.\d+)* # e.g. >=2 or >=1.2 etc
| \* # full wildcard
)
(?=,|$|\ |\||@) # trailing separator
}}x"#,
major = major
);
let mut matches: IndexMap<CaptureKey, Vec<(String, usize)>> = IndexMap::new();
if Preg::is_match_all_with_offsets3(&pattern, &pretty_constraint, Some(&mut matches))? {
let mut modified = pretty_constraint.clone();
let constraint_matches = matches
.get(&CaptureKey::ByName("constraint".to_string()))
.cloned()
.unwrap_or_default();
for match_ in constraint_matches.iter().rev() {
let match_str = &match_.0;
let match_offset = match_.1 as i64;
let suffix = if match_str.matches('.').count() == 2
&& version_without_suffix.matches('.').count() == 1
{
".0"
} else {
""
};
let replacement =
if match_str.starts_with('~') && match_str.matches('.').count() != 1 {
let mut version_bits: Vec<String> = version_without_suffix
.split('.')
.map(String::from)
.collect();
let needed_len = match_str.matches('.').count() + 1;
while version_bits.len() < needed_len {
version_bits.push("0".to_string());
}
let dots_in_match = match_str.matches('.').count();
format!("~{}", version_bits[..dots_in_match + 1].join("."))
} else if match_str == "*" || match_str.starts_with(">=") {
format!(">={}{}", version_without_suffix, suffix)
} else {
format!("{}{}", new_pretty_constraint, suffix)
};
let offset = match_offset as usize;
let length = Platform::strlen(match_str) as usize;
modified =
shirabe_php_shim::substr_replace(&modified, &replacement, offset, length);
}
let new_constraint = parser.parse_constraints(&modified)?;
if Intervals::is_subset_of(&new_constraint, constraint)?
&& Intervals::is_subset_of(constraint, &new_constraint)?
{
return Ok(pretty_constraint);
}
return Ok(modified);
}
Ok(pretty_constraint)
}
}
|