Skip to main content

xensec_internal_tools/
submit.rs

1// Copyright 2021 Citrix
2// SPDX-License-Identifier: MIT OR Apache-2.0
3// There is NO WARRANTY.
4
5use crate::prelude::*;
6
7#[derive(Debug,Clone)]
8#[derive(Ord,PartialOrd,Eq,PartialEq)]
9pub enum NothingDone {
10  Embargoed,
11  NoCves,
12  OnlyForeignCves,
13  MrOpen(String),
14  Completed,
15  ManualActionRequired(Vec<String>),
16}
17
18use NothingDone as N;
19use upstream::MrStatus as M;
20use analysis::CveInMrState as I;
21
22#[ext]
23impl<T> T where T: Ord + Clone {
24  fn umax(&mut self, other: T) { *self = max(self.clone(), other) }
25}
26
27impl Ctx {
28  #[throws(AE)]
29  pub fn submit1(&mut self, xsa: XsaNum, xstate: analysis::XsaState)
30                 -> Either<NothingDone, String /*MR#*/>
31  {
32    if ! xstate.public { return Left(NothingDone::Embargoed) }
33
34    let mut todo: Either<NothingDone, ()> = Left(N::NoCves);
35    let mut manual = vec![];
36
37    for (cve, st) in &xstate.cves {
38      match st {
39        I::Foreign   => todo.umax(Left(N::OnlyForeignCves)),
40        I::Completed => todo.umax(Left(N::Completed)),
41        I::NoBranch  => todo = Right(()), // can't both happen;
42        I::InMr      => todo = Right(()), // see XsaState.remote_branch
43        I::Broken(x) => manual.push(format!("{} broken: {}", cve, x)),
44        I::MissingFromBranch => manual.push(format!(
45          "{} missing from (remote tracking) branch {}",
46          cve, xsa.cvelist_branch_name(),
47        )),
48      }
49    }
50
51    if ! manual.is_empty() { return Left(N::ManualActionRequired(manual)) }
52    match todo {
53      Left(nothing) => return Left(nothing),
54      Right(()) => { }, // carry on
55    }
56
57    #[derive(Copy,Clone)] struct ThereIsNoMr;
58    let was_no_mr = match xstate.merge_req.as_ref().map(|s| &s.state) {
59      None if ! xstate.remote_branch => ThereIsNoMr,
60      Some(None) => ThereIsNoMr,
61      Some(Some(mr)) => return Left(match mr.status {
62        M::Open => N::MrOpen(format!(
63          "#{}", mr.num
64        )),
65        x => N::ManualActionRequired(vec![format!(
66          "MR #{} in state {:?}, CVEs not populated in upstream main branch",
67          &mr.num, &x
68        )]),
69      }),
70      None => panic!("mr not examined! {:?}", &xstate),
71    };
72
73    if ! xstate.remote_branch {
74      let ThereIsNoMr = was_no_mr;
75      let jpaths = self.xsas.generate_cve_json(xsa, &xstate)?;
76      let new_commit = self.cvelist.make_xsajson_commit
77        (&self.xsas, xsa, xstate.vsn, &jpaths)
78        .context("make new cvelist commit")?;
79
80      let cfg = &self.cfg;
81      self.cvelist.run_git(
82        self.want_remote_actions(xsa,"push",&new_commit)?,
83        "push", &mut |cmd: &mut Command| {
84          
85          cmd.arg("push");
86          if ! log_enabled!(log::Level::Debug) { cmd.arg("--quiet"); }
87          cmd.args(&[
88            &cfg.cvelist_remote_xensec,
89            &format!("{}:refs/heads/{}", &new_commit,
90                     xsa.cvelist_branch_name())
91          ]);
92          
93          Ok::<_,AE>(())
94        }
95      )
96        .context("make remote cvelist branch")?;
97    }
98
99    let ThereIsNoMr = was_no_mr;
100
101    let number = self.make_mr(xsa, &xstate)?;
102    Right(number)
103  }
104}
105
106impl NothingDone {
107  #[throws(fmt::Error)]
108  pub fn report(&self, w: &mut dyn fmt::Write, xsa: XsaNum) {
109    use NothingDone::*;
110    match self {
111      ManualActionRequired(s) => {
112        if s.len() > 0 {
113          for s in s {
114            writeln!(w, "{} NothingDone ManualActionRequired {}", xsa, s)?;
115          }
116        } else {
117          writeln!(w, "{} NothingDone ManualActionRequired", xsa)?;
118        }
119      }
120      MrOpen(number) => {
121        writeln!(w, "{} MrOpen {:?}", xsa, number)?;
122      }
123      Embargoed | NoCves | OnlyForeignCves | Completed => {
124        writeln!(w, "{} NothingDone {:?}", xsa, self)?;
125      }
126    }
127  }
128}