in focus/operations/src/clone.rs [620:672]
fn compute_and_store_initial_selection(
repo: &Repo,
projects_and_targets: Vec<String>,
template: Option<ClonedRepoTemplate>,
) -> Result<TargetSet> {
let mut selections = repo.selection_manager()?;
let operations = projects_and_targets
.iter()
.map(|value| Operation::new(OperationAction::default_add(), value))
.collect::<Vec<Operation>>();
// FIXME: ideally, we would check to make sure there is no `focus`
// directory, aand then create `focus/mandatory.projects.json` (and add it to
// the gitignore), but we don't have any facilities for modifying the
// mandatory projects programmatically.
let operations = match template {
None => operations,
Some(template) => operations
.into_iter()
.chain(
template
.entries()
.into_iter()
.map(|entry| Operation::new(OperationAction::default_add(), entry)),
)
.collect(),
};
let result = selections.process(&operations)?;
if !result.is_success() {
bail!("Selecting projects and targets failed");
}
selections.save()?;
let selection = selections.computed_selection()?;
let target_set = selections.compute_complete_target_set()?;
debug!(target_set = ?target_set, project_and_targets = ?projects_and_targets, selection_projects = ?selection.projects, selection_targets = ?selection.targets, "computing the target set");
// For open-source projects, it's likely that `.focus` will be created in
// their working tree and not ignored by default, which means that the next
// `focus add`/`focus sync` attempt will fail because the working tree is
// not clean. Improve the experience by ignoring `.focus` by default.
let info_dir = repo.git_dir().join("info");
std::fs::create_dir_all(&info_dir).context("Creating .git/info")?;
let exclude_path = info_dir.join("exclude");
let mut exclude_file = OpenOptions::new()
.append(true)
.open(exclude_path)
.context("Opening .git/info/exclude")?;
writeln!(exclude_file, "/.focus/").context("Writing initial .git/info/exclude")?;
Ok(target_set)
}