Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add an --overwrite option to pdm init #2166

Merged
merged 2 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2163.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an `--overwrite` option to `pdm init` to overwrite existing files(default False).
3 changes: 2 additions & 1 deletion src/pdm/cli/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _init_cookiecutter(self, project: Project, options: argparse.Namespace) -> N
def _init_builtin(self, project: Project, options: argparse.Namespace) -> None:
metadata = self.get_metadata_from_input(project, options)
with ProjectTemplate(options.template) as template:
template.generate(project.root, metadata)
template.generate(project.root, metadata, options.overwrite)
project.pyproject.reload()

def set_interactive(self, value: bool) -> None:
Expand Down Expand Up @@ -185,6 +185,7 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
"template", nargs="?", help="Specify the project template, which can be a local path or a Git URL"
)
parser.add_argument("generator_args", nargs=argparse.REMAINDER, help="Arguments passed to the generator")
parser.add_argument("-r", "--overwrite", action="store_true", help="Overwrite existing files")
parser.set_defaults(search_parent=False, generator="builtin")

def set_python(self, project: Project, python: str | None, hooks: HookManager) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/pdm/cli/completions/pdm.bash
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ _pdm_a919b69078acdf0a_complete()
;;

(init)
opts="--backend --cookiecutter --copier --global --help --lib --non-interactive --project --python --skip --verbose"
opts="--backend --cookiecutter --copier --global --help --lib --non-interactive --overwrite --project --python --skip --verbose"
;;

(install)
Expand Down
1 change: 1 addition & 0 deletions src/pdm/cli/completions/pdm.fish
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ complete -c pdm -A -n '__fish_seen_subcommand_from init' -l global -d 'Use the g
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l help -d 'Show this help message and exit.'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l lib -d 'Create a library project'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l non-interactive -d 'Don\'t ask questions but use default values'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l overwrite -d 'Overwrite existing files'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__ [env var: PDM_PROJECT]'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l python -d 'Specify the Python version/path to use'
complete -c pdm -A -n '__fish_seen_subcommand_from init' -l skip -d 'Skip some tasks and/or hooks by their comma-separated names. Can be supplied multiple times. Use ":all" to skip all hooks. Use ":pre" and ":post" to skip all pre or post hooks.'
Expand Down
2 changes: 1 addition & 1 deletion src/pdm/cli/completions/pdm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ function TabExpansion($line, $lastWord) {
"init" {
$completer.AddOpts(
@(
[Option]::new(@("-g", "--global", "--non-interactive", "-n", "--python", "--lib", "--copier", "--cookiecutter")),
[Option]::new(@("-g", "--global", "--non-interactive", "-n", "--python", "--lib", "--copier", "--cookiecutter", "--overwrite")),
$projectOption,
$skipOption,
[Option]::new(@("--backend")).WithValues(@("pdm-backend", "setuptools", "flit", "hatching", "pdm-pep517"))
Expand Down
1 change: 1 addition & 0 deletions src/pdm/cli/completions/pdm.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ _pdm() {
{-g,--global}'[Use the global project, supply the project root with `-p` option]'
{-n,--non-interactive}"[Don't ask questions but use default values]"
{-k,--skip}'[Skip some tasks and/or hooks by their comma-separated names]'
{-r,--overwrite}'[Overwrite existing files]'
'--backend[Specify the build backend]:backend:(pdm-backend setuptools hatchling flit pdm-pep517)'
'--lib[Create a library project]'
'--python[Specify the Python version/path to use]:python:'
Expand Down
8 changes: 5 additions & 3 deletions src/pdm/cli/templates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __enter__(self) -> "ProjectTemplate":
def __exit__(self, *args: Any) -> None:
shutil.rmtree(self._path, ignore_errors=True)

def generate(self, target_path: Path, metadata: dict[str, Any]) -> None:
def generate(self, target_path: Path, metadata: dict[str, Any], overwrite: bool = False) -> None:
from pdm.compat import tomllib

def replace_all(path: str, old: str, new: str) -> None:
Expand Down Expand Up @@ -74,7 +74,7 @@ def replace_all(path: str, old: str, new: str) -> None:
replace_all(os.path.join(root, f), import_name, new_import_name)

target_path.mkdir(exist_ok=True, parents=True)
self.mirror(self._path, target_path, [self._path / "pyproject.toml"])
self.mirror(self._path, target_path, [self._path / "pyproject.toml"], overwrite=overwrite)
self._generate_pyproject(target_path / "pyproject.toml", metadata)

def prepare_template(self) -> None:
Expand All @@ -94,14 +94,16 @@ def mirror(
dst: Path,
skip: list[ST] | None = None,
copyfunc: Callable[[ST, Path], Any] = shutil.copy2, # type: ignore[assignment]
*,
overwrite: bool = False,
) -> None:
if skip and src in skip:
return
if src.is_dir():
dst.mkdir(exist_ok=True)
for child in src.iterdir():
ProjectTemplate.mirror(child, dst / child.name, skip, copyfunc)
else:
elif overwrite or not dst.exists():
copyfunc(src, dst)

@staticmethod
Expand Down