% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/local_repo_anonymize.R
\name{local_repo_anonymize}
\alias{local_repo_anonymize}
\title{Anonymize a local repo or grading project}
\usage{
local_repo_anonymize(
  path,
  roster,
  cols = tidyselect::any_of(c("name", "first", "last", "email", "netid", "github")),
  output = NULL,
  types = c(".md", ".qmd", ".[Rr]md", ".txt", ".csv", ".tsv", ".html?", ".[Rr]", ".py",
    ".ipynb", ".json", ".ya?ml", ".tex", ".bib", ".toml", ".[Rr]proj"),
  git_history = c("delete", "keep"),
  prompt = interactive()
)
}
\arguments{
\item{path}{Character. Path to a git repository, a directory of repositories,
or a grading project folder (one containing a \verb{repos/} subdirectory of
cloned repositories, e.g. as produced by \code{\link[=org_grade_assignment]{org_grade_assignment()}}).}

\item{roster}{Either a path to a roster CSV file or a data frame. Each row is
treated as one student.}

\item{cols}{<\code{\link[dplyr:dplyr_tidy_select]{tidy-select}}> Roster columns whose
values should be stripped from the contents. Defaults to the \code{name},
\code{first}, \code{last}, \code{email}, \code{netid}, and \code{github} columns when present.}

\item{output}{Character. Directory to write the anonymized copy to. Defaults
to \verb{<path>_anon}. Set \code{output = path} to modify the folder in place (gated by
a confirmation prompt when \code{prompt = TRUE}).}

\item{types}{Character. Regular expressions matched against the end of each
file name to decide which files are treated as text and scanned. Defaults to
common text formats found in student work (markdown, R / Python source,
notebooks, html, csv, yaml, ...).}

\item{git_history}{Character. How each repository's git history is handled.
Either \code{"delete"} (default, remove the \code{.git} directory entirely) or \code{"keep"}
(leave it untouched, retaining the un-anonymized history).}

\item{prompt}{Logical. Prompt for confirmation before modifying a folder in
place. Defaults to \code{\link[=interactive]{interactive()}}.}
}
\value{
Invisibly, a list with two tibbles: \code{text} (files scrubbed and
replacements made per directory) and \code{git} (the action taken per repo).
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}

Makes a best-effort pass over a local git repository, a directory of
repositories, or a grading project created by \code{\link[=org_grade_assignment]{org_grade_assignment()}} and
removes student personally identifying information (PII). Two things happen:
\itemize{
\item \strong{File contents} - every text file is scanned and any roster-derived value
(names, NetIDs, emails, GitHub usernames, ...) is replaced with a stable
per-student token (e.g. \code{student_07}).
\item \strong{Git history} - each repository's \code{.git} directory is either deleted
outright (the default) or kept untouched.
}
}
\details{
Git history cannot be reliably anonymized while also being preserved. Even
after rewriting commit author and committer identities, the \emph{original file
contents} of older commits remain recoverable (\verb{git show <old-sha>:README.md}),
and real names routinely survive in commit messages and branch names. Because
anyone you hand the repository to receives its full history, there are only two
honest options, selected with \code{git_history}:
\itemize{
\item \code{"delete"} (default) - remove each repository's \code{.git} directory entirely.
The result is the scrubbed working tree with no recoverable history. This is
the safe choice for sharing student work.
\item \code{"keep"} - leave \code{.git} untouched. The working-tree files are still scrubbed,
but the original commit history (with real names and emails) is retained, so
the result is \strong{not} safe to distribute.
}

The function works on a \emph{copy} by default (\verb{<path>_anon}), leaving the original
intact, so deleting history is non-destructive to your working copy.

Only files whose names match \code{types} are scanned, so binary and other non-text
files are skipped by design. Matching is best effort: word boundaries are used
for names / NetIDs to avoid clobbering unrelated text, but short or common
names may still over-match, and HTML-entity-encoded names are not detected.
Anonymization is roster-driven, so anyone absent from the roster (e.g. a
student who later dropped) will not be matched.
}
\examples{
\dontrun{
local_repo_anonymize(
  "grading/hw1",
  roster = "rosters/hw1_roster.csv"
)

# scrub text but keep history, choosing the columns explicitly
local_repo_anonymize(
  "grading/hw1",
  roster = roster_df,
  cols = c(name, netid, email),
  git_history = "keep"
)
}

}
