gradle_sync/
buildgradle.rs

1use 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}