git_policy_cli/
lfs_bounded_push.rs1use super::auto_push_single_flight::{PushAttempt, PushGit, SingleFlightError, git_command, run_query};
17use super::bounded_push::{STOP_GRACE, apply_low_speed_defaults, push_deadline, run_bounded_push, strip_one_line_break};
19use super::lfs_push_precheck::lfs_refusal;
21use super::lfs_object_plan::narrow_plan;
23use super::lfs_upload::run_upload_bounded;
25use super::repo_read_layout::read_layout_in;
27use super::lfs_pre_push::plan_failed_message;
28use super::lfs_upload_plan::{Query, plan_upload, read_settings};
29use std::ffi::OsString;
31
32const REFUSED_EXIT_CODE: i64 = 1;
34
35pub fn run_push(git: &PushGit, arguments: &[OsString]) -> Result<PushAttempt, SingleFlightError> {
45 let region: &[OsString] = arguments.get(1..).unwrap_or_default();
46 if git.lfs {
47 if let Some(refusal) = lfs_refusal(&[], region, git.environment.as_slice()) {
48 return Ok(PushAttempt {
49 exit_code: REFUSED_EXIT_CODE,
50 output: strip_one_line_break(refusal.as_str()).to_owned(),
51 });
52 }
53 let mut query = |query_arguments: &[&str]| -> Result<String, String> {
54 let owned: Vec<OsString> = query_arguments.iter().map(OsString::from).collect();
55 let output = run_query(git, owned.as_slice()).map_err(|error| {
56 return error.to_string();
57 })?;
58 let text: String = String::from_utf8_lossy(output.stdout.as_slice()).trim().to_owned();
59 return match output.code {
60 Some(0) => Ok(text),
61 Some(1) if text.is_empty() => Ok(text),
62 code => Err(format!("exited with {code:?}: {}", String::from_utf8_lossy(output.stderr.as_slice()).trim())),
63 };
64 };
65 let planned = read_settings(&mut query as Query<'_>).and_then(|settings| {
66 return plan_upload(&[], region, git.environment.as_slice(), git.cwd.as_path(), settings.as_slice(), &mut query);
67 });
68 match planned {
69 Ok(Some(plan)) => {
70 let layout = read_layout_in(git.cwd.as_path(), git.environment.as_slice());
71 if let Some(narrowed) = narrow_plan(plan, layout.as_ref())
72 && let Some(failed) = run_upload_bounded(git, &narrowed)? {
73 return Ok(failed);
74 }
75 }
76 Ok(None) => {}
77 Err(error) => {
78 return Ok(PushAttempt {
79 exit_code: REFUSED_EXIT_CODE,
80 output: strip_one_line_break(plan_failed_message(error.0.as_str()).as_str()).to_owned(),
81 });
82 }
83 }
84 }
85 let mut command = git_command(git, arguments);
86 apply_low_speed_defaults(&mut command, git.environment.as_slice());
87 return run_bounded_push(command, push_deadline(git.environment.as_slice()), STOP_GRACE, git.environment.as_slice());
88}