gradle_sync/
buildgradle.rs1use semver::Version;
2use regex::{Regex, Captures};
3use configfile::ConfigurationFormat;
4use error::GradleResult;
5use std::io::Read;
6use std::io::{BufReader, BufRead};
7use error::Error;
8use version::GradleVersion;
9
10pub struct BuildGradleContent {
11 lines: Vec<String>,
12 version: GradleVersion,
13 modified: bool
14}
15
16impl ConfigurationFormat for BuildGradleContent {
17 fn from<R: Read>(reader: R) -> GradleResult<Self>{
18 let mut version_code: Option<u32> = None;
19 let mut version_name: Option<Version> = None;
20
21 let f = BufReader::new(reader);
22 let mut lines: Vec<String> = vec!();
23 for result_line in f.lines() {
24 let line = result_line?;
25 if version_code.is_none() {
26 version_code = parse_version_code_line(&line);
27 }
28 if version_name.is_none() {
29 version_name = parse_version_name_line(&line);
30 }
31 lines.push(line);
32 }
33 if version_code.is_none() {
34 return Err(Error::VersionNotFound("failed to find versionCode".to_string()))
35 }
36 if version_name.is_none() {
37 return Err(Error::VersionNotFound("failed to find versionName".to_string()))
38 }
39 Ok(Self{
40 lines,
41 version: GradleVersion::new(
42 version_code.unwrap(),
43 version_name.unwrap()
44 ),
45 modified: false
46 })
47 }
48 fn current_version(&self) -> GradleResult<&GradleVersion> {
49 Ok(&self.version)
50 }
51 fn is_modified(&self) -> bool {
52 self.modified
53 }
54 fn sync_version(&mut self, new_version: &Version) -> GradleResult<()> {
55 if self.version.synchronize_version(new_version)? {
56 self.modified = true
57 }
58 Ok(())
59 }
60 fn lines(&self) -> Vec<String> {
61 self.lines.iter().map(|line|{
62 let line = replace_version_code(line.clone(), self.version.code());
63 let line = replace_version_name(line, self.version.version());
64 line
65 }).collect()
66 }
67}
68
69pub fn parse_version_code_line(line: &str) -> Option<u32> {
70 let re = Regex::new(r"versionCode\s+(?P<code>\d+)").unwrap();
71 let caps = re.captures(line);
72 match caps {
73 Some(caps) => {
74 let code: u32 = (&caps["code"]).parse().unwrap();
75 Some(code)
76 },
77 None => None
78 }
79}
80
81pub fn parse_version_name_line(line: &str) -> Option<Version> {
82 let re = Regex::new(r#"versionName\s+"(?P<name>[\d.]+)""#).unwrap();
83 let caps = re.captures(line);
84 match caps {
85 Some(caps) => {
86 match Version::parse(&caps["name"]) {
87 Ok(version) => Some(version),
88 Err(_) => None
89 }
90 },
91 None => None
92 }
93}
94
95pub fn replace_version_code(line: String, version_code: u32) -> String {
96 let old_version_code = parse_version_code_line(&line);
97 match old_version_code {
98 Some(_) => {
99 let re = Regex::new(r#"versionCode\s+\d+"#).unwrap();
100 let new_line = re.replace(&line, |_: &Captures| {
101 format!("versionCode {}", version_code)
102 });
103 new_line.to_string()
104 },
105 None => line
106 }
107}
108
109pub fn replace_version_name(line: String, version: &Version) -> String {
110 let old_version_name = parse_version_name_line(&line);
111 match old_version_name {
112 Some(_) => {
113 let re = Regex::new(r#"versionName\s+"[\d.]+""#).unwrap();
114 let new_line = re.replace(&line, |_: &Captures| {
115 format!(r#"versionName "{}""#, version.to_string())
116 });
117 new_line.to_string()
118 },
119 None => line
120 }
121}