fn copy_local_branches()

in focus/operations/src/clone.rs [892:992]


fn copy_local_branches(
    dense_repo: &Repository,
    sparse_repo: &Repository,
    branch: &str,
    app: Arc<App>,
    days_of_history: u64,
) -> Result<()> {
    let branches = dense_repo
        .branches(Some(git2::BranchType::Local))
        .context("Failed to enumerate local branches in the dense repo")?;
    let mut valid_local_branches = Vec::new();

    for b in branches {
        let (b, _branch_type) = b?;
        let name = match b.name()? {
            Some(name) => name,
            None => {
                warn!(
                    "Skipping branch {:?} because it is not representable as UTF-8",
                    b.name_bytes()
                );
                continue;
            }
        };

        if name == branch {
            // Skip the primary branch since it should already be configured.
            continue;
        }

        debug!("Examining dense repo branch {}", name);
        let dense_commit = b
            .get()
            .peel_to_commit()
            .context("Failed to peel branch ref to commit")?;

        let dense_commit_date = DateTime::from_utc(
            NaiveDateTime::from_timestamp(dense_commit.time().seconds(), 0),
            Utc,
        )
        .date();

        let days_of_history: i64 = days_of_history.try_into()?;
        let shallow_since_datestamp = focus_util::time::date_at_day_in_past(days_of_history)?;

        if days_of_history > 0 {
            if dense_commit_date > shallow_since_datestamp {
                valid_local_branches.push((name.to_owned(), dense_commit.to_owned()));
            } else {
                warn!(
                    "Branch {} is older than the configured limit ({}). Rebase it if you would like it to be included in the new repo.",
                    name, shallow_since_datestamp
                );
            }
        }
    }

    let branch_list_output = valid_local_branches
        .iter()
        .map(|(name, _)| name.to_string())
        .collect::<Vec<String>>()
        .join(" ");

    let (mut cmd, scmd) = git_helper::git_command(app)?;
    let mut args: Vec<OsString> = vec!["fetch".into(), "--no-tags".into()];
    args.push("origin".into());
    valid_local_branches
        .iter()
        .for_each(|(name, _)| args.push(name.into()));
    scmd.ensure_success_or_log(
        cmd.current_dir(sparse_repo.path()).args(args),
        SandboxCommandOutput::Stderr,
    )
    .map(|_| ())
    .with_context(|| {
        format!(
            "Failed to fetch user branches ({}) for {}",
            branch_list_output,
            whoami::username()
        )
    })?;

    valid_local_branches.iter().for_each(|(name, dense_commit)| {
        match sparse_repo.find_commit(dense_commit.id()) {
            Ok(sparse_commit) => match sparse_repo.branch(name, &sparse_commit, false) {
                Ok(_new_branch) => {
                    info!("Created branch {} ({})", name, sparse_commit.id());
                }
                Err(e) => {
                    error!("Could not create branch {} in the sparse repo: {}", name, e);
                }
            },
            Err(_) => {
                error!("Could not create branch {} in the sparse repo because the associated commit ({}) does not exist!",
                    name, dense_commit.id());
            }
        }
    });

    Ok(())
}