Documentation
¶
Overview ¶
Package copier provides a Go port of Copier for rendering project templates.
It tracks the behavior of the upstream Python project at https://github.com/copier-org/copier while exposing a native Go library API. Copier templates, answers files, Git-based updates, and questionnaires are intended to remain compatible with upstream Copier wherever practical.
Index ¶
- Constants
- Variables
- func CloneTemplate(url, ref string, usePreReleases bool) (localPath string, resolvedRef string, err error)
- func Copy(src, dst string, opts ...Option) error
- func CopyDir(src, dst string) error
- func CopyFile(src, dst string) error
- func GitAdd(repoPath string) error
- func GitApplyDiff(repoPath string, diffContent []byte, contextLines int, reject bool) error
- func GitCommit(repoPath, message string) error
- func GitDiff(repoPath string, contextLines int) ([]byte, error)
- func GitInit(path string) error
- func IsBinary(path string) (bool, error)
- func IsGitInstalled() bool
- func IsGitURL(url string) bool
- func IsTemplateSuffix(path, suffix string) bool
- func LoadAnswersFile(path string) (map[string]any, error)
- func NormalizeURL(rawURL string) (string, bool)
- func ParseAnswer(q QuestionDef, raw any) (any, error)
- func Recopy(dst string, opts ...Option) error
- func RepoCommitDescription(repoPath string) (string, error)
- func RepoCommitHash(repoPath string) (string, error)
- func ResolveDefault(q QuestionDef, answers *AnswersMap, settings *Settings) any
- func ShouldAsk(q QuestionDef, renderer *Renderer, answers map[string]any) bool
- func StripTemplateSuffix(path, suffix string) string
- func SyncGitIndexExecutableBit(dstRoot, dstPath string, srcMode os.FileMode)
- func Update(dst string, opts ...Option) error
- func ValidateAnswer(q QuestionDef, answer any, renderer *Renderer, answers map[string]any) error
- func WalkTemplate(root string, excludeMatcher *PatternMatcher, ...) error
- func WriteAnswersFile(path string, answers map[string]any, metadata map[string]any) error
- type AnswersMap
- type CheckUpdateResult
- type Config
- type ConflictStrategy
- type Envops
- type InterruptError
- type LazyMap
- type MigrationDef
- type Operation
- type Option
- func WithAnswersFile(path string) Option
- func WithCleanupOnError(v bool) Option
- func WithConflict(s ConflictStrategy) Option
- func WithContextLines(n int) Option
- func WithData(data map[string]any) Option
- func WithDefaults(v bool) Option
- func WithExclude(patterns ...string) Option
- func WithOverwrite(v bool) Option
- func WithPreReleases(v bool) Option
- func WithPretend(v bool) Option
- func WithQuiet(v bool) Option
- func WithSkip(patterns ...string) Option
- func WithSkipAnswered(v bool) Option
- func WithSkipTasks(v bool) Option
- func WithUnsafe(v bool) Option
- func WithUserDefaults(defaults map[string]any) Option
- func WithVcsRef(ref string) Option
- type PatternMatcher
- type Phase
- type Prompter
- type QuestionDef
- type QuestionError
- type QuestionType
- type Renderer
- type Settings
- type TaskDef
- type TaskExecError
- type Template
- func (t *Template) Cleanup()
- func (t *Template) CopyRoot() string
- func (t *Template) Exclusions() []string
- func (t *Template) IsSecret(name string) bool
- func (t *Template) Metadata() map[string]any
- func (t *Template) MigrationTasks(stage string, fromVer, toVer *semver.Version) []TaskDef
- func (t *Template) MinVersion() *semver.Version
- type TemplateConfig
- type TemplateError
- type TerminalPrompter
- type ValidationError
- type VcsRef
Constants ¶
const AnswersFileName = ".copier-answers.yml"
AnswersFileName is the default file for storing copier answers.
const DefaultTemplateSuffix = ".jinja"
DefaultTemplateSuffix is the suffix identifying Jinja template files.
Variables ¶
var ( ErrUnsupportedVersion = errors.New("copier version not supported by template") ErrConfig = errors.New("template configuration error") ErrMultipleConfigs = errors.New("both copier.yml and copier.yaml found") ErrUnsafeTemplate = errors.New("template uses unsafe features; use WithUnsafe(true) or trust the repository") ErrExtensionNotFound = errors.New("jinja extension not found") ErrInteractiveNeeded = errors.New("interactive session required but not available") ErrInvalidType = errors.New("invalid question type") ErrPathNotAbsolute = errors.New("path must be absolute") ErrPathNotRelative = errors.New("path must be relative") ErrForbiddenPath = errors.New("path escapes destination directory") ErrYieldInFile = errors.New("yield tag found in file content") ErrMultipleYields = errors.New("multiple yield tags in a single path segment") ErrTaskFailed = errors.New("task execution failed") ErrInterrupted = errors.New("operation interrupted by user") )
Sentinel errors for type-checking with errors.Is.
var DefaultExclude = []string{
"copier.yaml",
"copier.yml",
"~*",
"*.py[co]",
"__pycache__",
".git",
".DS_Store",
".svn",
}
DefaultExclude contains patterns excluded from all template renders.
Functions ¶
func CloneTemplate ¶
func CloneTemplate(url, ref string, usePreReleases bool) (localPath string, resolvedRef string, err error)
CloneTemplate clones a git template to a temporary directory and checks out the specified ref. If ref is empty, the latest semver tag is used.
Uses the git CLI for cloning so that SSH keys, credential helpers, and other user-configured auth mechanisms work transparently.
func Copy ¶
Copy scaffolds a new project from a template.
src is the template source (local path or Git URL). dst is the destination directory (created if it does not exist).
err := copier.Copy("gh:user/template", "./myproject",
copier.WithData(map[string]any{"project_name": "myapp"}),
)
func GitApplyDiff ¶
GitApplyDiff applies a unified diff to a repository using the git command line. go-git does not support git apply, so we shell out.
func IsBinary ¶
IsBinary performs a simple heuristic to detect binary files by checking the first 8KB for null bytes.
func IsGitInstalled ¶
func IsGitInstalled() bool
IsGitInstalled reports whether git is available on PATH.
func IsTemplateSuffix ¶
IsTemplateSuffix reports whether the file path ends with the template suffix.
func LoadAnswersFile ¶
LoadAnswersFile reads a .copier-answers.yml file.
func NormalizeURL ¶
NormalizeURL expands shorthand URLs and detects git repositories. Supported shorthands: gh:org/repo, gl:org/repo, git+<url>.
func ParseAnswer ¶
func ParseAnswer(q QuestionDef, raw any) (any, error)
ParseAnswer converts a raw answer value to the expected Go type for the question.
func Recopy ¶
Recopy re-applies a template to a project, discarding the project's evolution and using the existing answers.
err := copier.Recopy("./myproject")
func RepoCommitDescription ¶
RepoCommitDescription returns a git describe-style reference for HEAD.
func RepoCommitHash ¶
RepoCommitHash returns the HEAD commit hash for a local git repository.
func ResolveDefault ¶
func ResolveDefault(q QuestionDef, answers *AnswersMap, settings *Settings) any
ResolveDefault returns the effective default for a question given all answer sources. Priority: Init → Last → UserDefaults → Settings → Question.Default.
func ShouldAsk ¶
func ShouldAsk(q QuestionDef, renderer *Renderer, answers map[string]any) bool
ShouldAsk evaluates the when condition for a question. Returns true if the question should be shown.
func StripTemplateSuffix ¶
StripTemplateSuffix removes the template suffix from a path.
func SyncGitIndexExecutableBit ¶
SyncGitIndexExecutableBit updates the destination git index mode when git is configured to ignore filesystem mode changes.
func Update ¶
Update updates an existing project to a newer version of its template. The destination must contain a .copier-answers.yml from a previous Copy.
err := copier.Update("./myproject",
copier.WithConflict(copier.ConflictInline),
)
func ValidateAnswer ¶
ValidateAnswer runs the question's validator template. Returns nil if valid, or a ValidationError if the validator returns a non-empty string.
func WalkTemplate ¶
func WalkTemplate(root string, excludeMatcher *PatternMatcher, fn func(relPath string, d fs.DirEntry) error) error
WalkTemplate walks the template directory and calls fn for each file/dir that is not excluded. Paths passed to fn are relative to root.
Types ¶
type AnswersMap ¶
type AnswersMap struct {
User map[string]any // Interactive answers from the current session.
Init map[string]any // Pre-set answers from --data flags.
Metadata map[string]any // Template metadata (_src_path, _commit).
Last map[string]any // Answers from a previous .copier-answers.yml.
UserDefaults map[string]any // User-configured defaults from settings.
Hidden map[string]bool // Questions whose answers should not be persisted.
}
AnswersMap holds layered answer data with defined precedence. Lookup order: User → Init → Metadata → Last → UserDefaults → Builtin.
func NewAnswersMap ¶
func NewAnswersMap() *AnswersMap
NewAnswersMap creates an AnswersMap with initialised maps.
func (*AnswersMap) Combined ¶
func (a *AnswersMap) Combined() map[string]any
Combined returns a flat map merging all layers in precedence order.
func (*AnswersMap) Get ¶
func (a *AnswersMap) Get(key string) (any, bool)
Get looks up a value following the precedence chain.
func (*AnswersMap) Remembered ¶
func (a *AnswersMap) Remembered() map[string]any
Remembered returns answers suitable for writing to the answers file, excluding hidden questions and metadata.
type CheckUpdateResult ¶
type CheckUpdateResult struct {
UpdateAvailable bool `json:"update_available"`
CurrentVersion string `json:"current_version"`
LatestVersion string `json:"latest_version"`
}
CheckUpdateResult describes whether a rendered project has a newer template version.
func CheckUpdate ¶
func CheckUpdate(dst string, opts ...Option) (CheckUpdateResult, error)
CheckUpdate checks whether dst was generated from an older template version.
type Config ¶
type Config struct {
// SrcPath is the template source (local path or Git URL).
SrcPath string
// DstPath is the destination directory.
DstPath string
// AnswersFile overrides the default answers file path (.copier-answers.yml).
AnswersFile string
// VcsRef selects a specific Git tag, branch, or commit. Empty means latest tag.
VcsRef string
// Data provides pre-set answers that skip interactive prompting.
Data map[string]any
// Defaults uses default values for all questions without prompting.
Defaults bool
// UserDefaults supplies fallback defaults for questions (lower priority than Data).
UserDefaults map[string]any
// Overwrite replaces existing files without asking.
Overwrite bool
// Skip lists patterns of files to leave untouched if they already exist.
Skip []string
// Exclude lists additional patterns of template files to ignore.
Exclude []string
// Pretend performs a dry run without writing any files.
Pretend bool
// Quiet suppresses informational output.
Quiet bool
// Unsafe allows templates that use tasks or other potentially dangerous features.
Unsafe bool
// SkipTasks skips execution of pre/post-copy tasks.
SkipTasks bool
// SkipAnswered skips questions whose answers are already known (update/recopy).
SkipAnswered bool
// UsePreReleases includes pre-release Git tags when selecting the latest version.
UsePreReleases bool
// CleanupOnError removes the destination directory if an error occurs during copy.
CleanupOnError bool
// Conflict sets the merge conflict strategy for updates ("inline" or "rej").
Conflict ConflictStrategy
// ContextLines sets the number of context lines in diffs for updates.
ContextLines int
}
Config holds all configuration for a copier operation. Use functional Option values to construct one via Copy, Update, or Recopy.
type ConflictStrategy ¶
type ConflictStrategy string
ConflictStrategy defines how merge conflicts are handled during updates.
const ( ConflictInline ConflictStrategy = "inline" ConflictReject ConflictStrategy = "rej" )
type Envops ¶
type Envops struct {
BlockStartString string `yaml:"block_start_string"`
BlockEndString string `yaml:"block_end_string"`
VariableStartString string `yaml:"variable_start_string"`
VariableEndString string `yaml:"variable_end_string"`
CommentStartString string `yaml:"comment_start_string"`
CommentEndString string `yaml:"comment_end_string"`
Undefined string `yaml:"undefined"`
}
Envops configures template delimiters (mirrors Jinja2's Environment options).
func DefaultEnvops ¶
func DefaultEnvops() Envops
DefaultEnvops returns pongo2/Jinja2 standard delimiters.
type InterruptError ¶
InterruptError carries partial answers when the user interrupts a prompt session.
func (*InterruptError) Error ¶
func (e *InterruptError) Error() string
func (*InterruptError) Unwrap ¶
func (e *InterruptError) Unwrap() error
type LazyMap ¶
type LazyMap[V any] struct { // contains filtered or unexported fields }
LazyMap is a concurrent-safe map where values are lazily computed on first access. Compute functions are called at most once per key.
func NewLazyMap ¶
NewLazyMap creates a LazyMap with the given compute functions.
type MigrationDef ¶
type MigrationDef struct {
Version string `yaml:"version"`
Before []TaskDef `yaml:"before"`
After []TaskDef `yaml:"after"`
}
MigrationDef defines a migration step between template versions.
type Operation ¶
type Operation string
Operation represents the type of copier operation being performed.
type Option ¶
type Option func(*Config)
Option configures a copier operation.
func WithAnswersFile ¶
WithAnswersFile sets a custom path for the copier answers file.
func WithCleanupOnError ¶
WithCleanupOnError removes the destination on failure (default: true).
func WithConflict ¶
func WithConflict(s ConflictStrategy) Option
WithConflict sets the merge conflict strategy for updates.
func WithContextLines ¶
WithContextLines sets the number of diff context lines for updates.
func WithDefaults ¶
WithDefaults uses all default values instead of prompting.
func WithExclude ¶
WithExclude adds patterns for template files to exclude from rendering.
func WithOverwrite ¶
WithOverwrite allows overwriting existing files without confirmation.
func WithPreReleases ¶
WithPreReleases includes pre-release tags when selecting the latest version.
func WithPretend ¶
WithPretend enables dry-run mode (no files written).
func WithSkipAnswered ¶
WithSkipAnswered skips questions that already have answers from a previous run.
func WithSkipTasks ¶
WithSkipTasks disables execution of template tasks.
func WithUnsafe ¶
WithUnsafe allows templates with tasks or other potentially dangerous features.
func WithUserDefaults ¶
WithUserDefaults supplies fallback defaults for questions.
func WithVcsRef ¶
WithVcsRef pins the template to a specific Git reference (tag, branch, commit).
type PatternMatcher ¶
type PatternMatcher struct {
// contains filtered or unexported fields
}
PatternMatcher compiles glob patterns and provides matching against relative paths.
func NewPatternMatcher ¶
func NewPatternMatcher(patterns []string) *PatternMatcher
NewPatternMatcher compiles the given glob patterns.
func (*PatternMatcher) Matches ¶
func (m *PatternMatcher) Matches(path string) bool
Matches reports whether path matches any of the compiled patterns.
type Prompter ¶
type Prompter interface {
Ask(q QuestionDef, currentAnswers map[string]any) (any, error)
Confirm(message string, defaultVal bool) (bool, error)
}
Prompter handles interactive question prompting. It is an interface to allow testing and alternative UIs.
type QuestionDef ¶
type QuestionDef struct {
Name string
Type QuestionType `yaml:"type"`
Help string `yaml:"help"`
Choices any `yaml:"choices"` // []any or map[string]any or string (Jinja)
Multiselect bool `yaml:"multiselect"`
Default any `yaml:"default"`
Secret bool `yaml:"secret"`
Multiline any `yaml:"multiline"` // bool or string
Placeholder string `yaml:"placeholder"`
Validator string `yaml:"validator"`
When any `yaml:"when"` // bool or string (Jinja condition)
}
QuestionDef holds the raw question definition from copier.yml.
type QuestionError ¶
QuestionError wraps errors related to question processing.
func (*QuestionError) Error ¶
func (e *QuestionError) Error() string
func (*QuestionError) Unwrap ¶
func (e *QuestionError) Unwrap() error
type QuestionType ¶
type QuestionType string
QuestionType defines the expected answer type for a question.
const ( TypeStr QuestionType = "str" TypeInt QuestionType = "int" TypeFloat QuestionType = "float" TypeBool QuestionType = "bool" TypeYAML QuestionType = "yaml" TypeJSON QuestionType = "json" TypePath QuestionType = "path" )
type Renderer ¶
type Renderer struct {
// contains filtered or unexported fields
}
Renderer handles Jinja2-compatible template rendering using pongo2.
func NewRenderer ¶
NewRenderer creates a Renderer with the given base context, template directory, and optional custom delimiters.
func (*Renderer) RenderFile ¶
RenderFile renders a template file to the destination path.
func (*Renderer) RenderPath ¶
RenderPath renders a path string, expanding template expressions in path segments. Returns all expanded paths (multiple if yield tags are used).
type Settings ¶
type Settings struct {
// Defaults maps question names to default values.
Defaults map[string]any `yaml:"defaults,omitempty"`
// Trust lists repository URLs or prefixes that are allowed to run unsafe features.
Trust []string `yaml:"trust,omitempty"`
}
Settings holds user-level copier configuration loaded from disk.
func LoadSettings ¶
LoadSettings reads the user settings file. It checks, in order:
- $COPIER_SETTINGS_PATH
- <XDG_CONFIG_HOME>/copier/settings.yml
Returns an empty Settings (not an error) if no file exists.
func (*Settings) DefaultFor ¶
DefaultFor returns the default value for a question, if one is configured.
type TaskDef ¶
type TaskDef struct {
Cmd any `yaml:"cmd"` // string or []string
Condition any `yaml:"condition"` // string or bool, default true
WorkingDirectory string `yaml:"working_directory"`
}
TaskDef defines a command to run during template operations.
type TaskExecError ¶
TaskExecError wraps errors from task execution with the command and exit code.
func (*TaskExecError) Error ¶
func (e *TaskExecError) Error() string
func (*TaskExecError) Unwrap ¶
func (e *TaskExecError) Unwrap() error
type Template ¶
type Template struct {
// URL is the original template URL or local path.
URL string
// LocalPath is the absolute path to the template on disk (cloned or direct).
LocalPath string
// Temporary is true when LocalPath points to a clone that should be removed.
Temporary bool
// Ref is the resolved git reference (tag, branch, commit).
Ref string
// CommitHash is the full git commit hash of the checked-out template.
CommitHash string
// CommitDescription is the git describe-style reference saved for updates.
CommitDescription string
// Config holds parsed copier.yml settings (keys prefixed with _).
Config TemplateConfig
// Questions holds parsed question definitions (non-prefixed keys).
Questions []QuestionDef
// contains filtered or unexported fields
}
Template represents a loaded copier template with its configuration.
func LoadTemplate ¶
LoadTemplate loads a template from a local path or Git URL. If url is a Git URL, it clones the repository. ref selects a specific version.
func (*Template) Cleanup ¶
func (t *Template) Cleanup()
Cleanup removes temporary template clones created while loading Git templates.
func (*Template) CopyRoot ¶
CopyRoot returns the root directory for template files, accounting for subdirectory.
func (*Template) Exclusions ¶
Exclusions returns the combined list of exclude patterns (defaults + template config).
func (*Template) MigrationTasks ¶
MigrationTasks returns tasks for a given migration stage (before/after) filtered by version range.
func (*Template) MinVersion ¶
MinVersion returns the parsed minimum copier version, or nil if not set.
type TemplateConfig ¶
type TemplateConfig struct {
AnswersFile string `yaml:"_answers_file"`
Subdirectory string `yaml:"_subdirectory"`
TemplateSuffix string `yaml:"_templates_suffix"`
Exclude []string `yaml:"_exclude"`
SkipIfExists []string `yaml:"_skip_if_exists"`
Tasks []TaskDef `yaml:"_tasks"`
JinjaExtensions []string `yaml:"_jinja_extensions"`
SecretQuestions []string `yaml:"_secret_questions"`
PreserveSymlinks bool `yaml:"_preserve_symlinks"`
MinCopierVersion string `yaml:"_min_copier_version"`
Envops Envops `yaml:"_envops"`
ExternalData map[string]string `yaml:"_external_data"`
MessageBeforeCopy string `yaml:"_message_before_copy"`
MessageAfterCopy string `yaml:"_message_after_copy"`
MessageBeforeUpdate string `yaml:"_message_before_update"`
MessageAfterUpdate string `yaml:"_message_after_update"`
Migrations []MigrationDef `yaml:"_migrations"`
}
TemplateConfig holds configuration from copier.yml underscore-prefixed keys.
type TemplateError ¶
TemplateError wraps errors related to template loading or configuration.
func (*TemplateError) Error ¶
func (e *TemplateError) Error() string
func (*TemplateError) Unwrap ¶
func (e *TemplateError) Unwrap() error
type TerminalPrompter ¶
type TerminalPrompter struct{}
TerminalPrompter implements Prompter using charmbracelet/huh for terminal UI.
func NewTerminalPrompter ¶
func NewTerminalPrompter() *TerminalPrompter
NewTerminalPrompter creates a new terminal prompter.
func (*TerminalPrompter) Ask ¶
func (p *TerminalPrompter) Ask(q QuestionDef, currentAnswers map[string]any) (any, error)
Ask prompts the user for an answer to the given question.
type ValidationError ¶
ValidationError is returned when a question answer fails validation.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
copier
command
Package main provides the copier CLI.
|
Package main provides the copier CLI. |
|
internal
|
|
|
pathutil
Package pathutil provides path validation and manipulation helpers.
|
Package pathutil provides path validation and manipulation helpers. |
|
textutil
Package textutil provides text manipulation helpers.
|
Package textutil provides text manipulation helpers. |
|
version
Package version holds the build-time version string.
|
Package version holds the build-time version string. |