1use std::borrow::Cow;
10
11use git_workarea::GitContext;
12use log::error;
13
14use crate::context::CheckGitContext;
15
16#[derive(Debug)]
21pub struct SubmoduleContext<'a> {
22 pub name: Cow<'a, str>,
24 pub path: Cow<'a, str>,
26 pub url: Cow<'a, str>,
28 pub branch: Cow<'a, str>,
30
31 pub context: GitContext,
33}
34
35impl<'a> SubmoduleContext<'a> {
36 pub fn new(ctx: &'a CheckGitContext, diff_path: &str) -> Option<Self> {
40 ctx.submodule_config()
41 .iter()
42 .filter_map(|(name, config)| {
44 config
45 .get("url")
46 .and_then(|url| config.get("path").map(|path| (url, path)))
47 .and_then(|(url, path)| {
48 if path == diff_path {
49 let branch = config.get("branch").map(String::as_str);
50
51 Some((name, path, url, branch))
52 } else {
53 None
54 }
55 })
56 })
57 .next()
59 .map(|(name, path, url, branch)| {
61 let gitdir = ctx.gitdir().join("modules").join(name);
62 let context = GitContext::new(&gitdir);
63
64 let branch = if let Some(branch) = branch {
65 branch.into()
66 } else {
67 match context.default_branch() {
68 Ok(Some(branch)) => branch.into(),
69 Ok(None) => "master".into(),
70 Err(err) => {
71 error!(
72 "failed to determine the default branch in {}: {}",
73 gitdir.display(),
74 err,
75 );
76
77 "master".into()
78 },
79 }
80 };
81
82 SubmoduleContext {
83 name: name.into(),
84 path: path.into(),
85 url: url.into(),
86 branch,
87
88 context,
89 }
90 })
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use std::path::Path;
97
98 use git_workarea::{CommitId, Identity};
99
100 use crate::context::CheckGitContext;
101 use crate::test::*;
102 use crate::utils::SubmoduleContext;
103
104 const DEFAULT_NAME_SUBMODULE: &str = "fe90ee22ae3ce4b4dc41f8d0876e59355ff1e21c";
105 const CUSTOM_NAME_SUBMODULE: &str = "4f645a7cc4c6a210193e1df5931f6336fa10459f";
106
107 fn make_submodule_context(path: &Path, commit: &CommitId) -> CheckGitContext {
108 let ctx = make_context_submodule(path, commit);
109 let workarea = ctx.prepare(commit).unwrap();
110 let who = Identity::new("Rust Git Checks Tests", "rust-git-checks@example.com");
111
112 CheckGitContext::new(workarea, who)
113 }
114
115 #[test]
116 fn test_submodule_context_no_exist() {
117 let tempdir = make_temp_dir();
118 let ctx = make_submodule_context(tempdir.path(), &CommitId::new(DEFAULT_NAME_SUBMODULE));
119 assert!(SubmoduleContext::new(&ctx, "no-submodule").is_none());
120 }
121
122 #[test]
123 fn test_submodule_context_default_name() {
124 let tempdir = make_temp_dir();
125 let ctx = make_submodule_context(tempdir.path(), &CommitId::new(DEFAULT_NAME_SUBMODULE));
126 let sub_ctx = SubmoduleContext::new(&ctx, "submodule").unwrap();
127
128 assert_eq!(sub_ctx.name, "submodule");
129 assert_eq!(sub_ctx.path, "submodule");
130 assert_eq!(
131 sub_ctx.url,
132 "https://gitlab.kitware.com/utils/test-repo.git",
133 );
134 assert_eq!(sub_ctx.branch, "master");
135 assert_eq!(
136 sub_ctx.context.gitdir(),
137 tempdir.path().join("origin/.git/modules/submodule"),
138 );
139 }
140
141 #[test]
142 fn test_submodule_context_custom_name() {
143 let tempdir = make_temp_dir();
144 let ctx = make_submodule_context(tempdir.path(), &CommitId::new(CUSTOM_NAME_SUBMODULE));
145 let sub_ctx = SubmoduleContext::new(&ctx, "submodule").unwrap();
146
147 assert_eq!(sub_ctx.name, "custom-name");
148 assert_eq!(sub_ctx.path, "submodule");
149 assert_eq!(
150 sub_ctx.url,
151 "https://gitlab.kitware.com/utils/test-repo.git",
152 );
153 assert_eq!(sub_ctx.branch, "master");
154 assert_eq!(
155 sub_ctx.context.gitdir(),
156 tempdir.path().join("origin/.git/modules/custom-name"),
157 );
158 }
159}