1use std::env;
23use std::fmt;
24
25#[derive(PartialEq, Debug)]
26pub enum CiService {
27 Travis,
28 Circle,
29 Unknown,
30}
31
32macro_rules! err {
33 ($expr:expr) => {
34 match $expr {
35 Ok(val) => Some(val),
36 Err(e) => match e {
37 ::std::env::VarError::NotPresent => None,
38 _ => panic!(e),
39 }
40 }
41 }
42}
43
44macro_rules! lang_version {
45 ($lang:expr, $name:ident) => {
46 pub fn $name(&self) -> Option<String> {
48 match self.service {
49 CiService::Travis => err!(env::var(format!("TRAVIS_{}_VERSION", $lang))),
50 _ => None,
51 }
52 }
53 }
54}
55
56pub struct Ci {
57 service: CiService,
58}
59impl Ci {
60 pub fn new() -> Option<Self> {
61 let s = Ci::which_ci();
62 match s {
63 CiService::Travis | CiService::Circle => Some(Ci { service: s }),
64 _ => None,
65 }
66 }
67
68 pub fn which_ci() -> CiService {
69 match (err!(env::var("TRAVIS")), err!(env::var("CIRCLECI"))) {
70 (Some(_), None) => CiService::Travis,
71 (None, Some(_)) => CiService::Circle,
72 _ => CiService::Unknown,
73 }
74 }
75
76 pub fn lang() -> Option<String> {
78 err!(env::var("LANG"))
79 }
80
81 pub fn path() -> Option<String> {
83 err!(env::var("PATH"))
84 }
85
86 pub fn home() -> Option<String> {
88 err!(env::var("HOME"))
89 }
90
91 pub fn is_travis(&self) -> bool {
92 match self.service {
93 CiService::Travis => true,
94 _ => false,
95 }
96 }
97
98 pub fn is_circle(&self) -> bool {
99 match self.service {
100 CiService::Circle => true,
101 _ => false,
102 }
103 }
104
105 pub fn branch(&self) -> Option<String> {
106 match self.service {
107 CiService::Circle => err!(env::var("CIRCLE_BRANCH")),
108 CiService::Travis => err!(env::var("TRAVIS_BRANCH")),
109 _ => None,
110 }
111 }
112
113 pub fn build_url(&self) -> Option<String> {
117 match self.service {
118 CiService::Circle => err!(env::var("CIRCLE_BUILD_URL")),
119 _ => None,
120 }
121 }
122
123 pub fn build_id(&self) -> Option<String> {
126 match self.service {
127 CiService::Circle => err!(env::var("CIRCLE_BUILD_NUM")),
128 CiService::Travis => err!(env::var("TRAVIS_BUILD_NUMBER")),
129 _ => None,
130 }
131 }
132
133 pub fn build_dir(&self) -> Option<String> {
137 match self.service {
138 CiService::Travis => err!(env::var("TRAVIS_BUILD_DIR")),
139 _ => None,
140 }
141 }
142
143 pub fn commit(&self) -> Option<String> {
145 match self.service {
146 CiService::Circle => err!(env::var("CIRCLE_SHA1")),
147 CiService::Travis => err!(env::var("TRAVIS_COMMIT")),
148 _ => None,
149 }
150 }
151
152 pub fn pull_request(&self) -> Option<String> {
156 match self.service {
157 CiService::Circle => err!(env::var("CIRCLE_PR_NUMBER")),
158 CiService::Travis => {
159 let pr = err!(env::var("TRAVIS_PULL_REQUEST")).unwrap_or("false".to_string());
160 if pr == "false" {
161 None
162 } else {
163 Some(pr)
164 }
165 }
166 _ => None,
167 }
168 }
169
170 lang_version!("DART", dart);
171 lang_version!("GO", go);
172 lang_version!("HAXE", haxe);
173 lang_version!("JDK", java);
174 lang_version!("JULIA", julia);
175 lang_version!("NODE", node);
176 lang_version!("OTP", otp);
177 lang_version!("PERL", perl);
178 lang_version!("PHP", php);
179 lang_version!("PYTHON", python);
180 lang_version!("R", r);
181 lang_version!("RUBY", ruby);
182 lang_version!("RUST", rust);
183 lang_version!("SCALA", scala);
184}
185impl fmt::Display for Ci {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 write!(f, "Continuous Integration Service: {:?}", self.service)
188 }
189}