{"record":{"id":"39221c168c4c85d8","repo":"GyulyVGC/sniffnet","slug":"refusing-to-overwrite-an-existing-release-in-output-use","errorCode":null,"errorMessage":"Refusing to overwrite an existing release in {output}; use --output with a fresh directory","messagePattern":"Refusing to overwrite an existing release in (.+?); use --output with a fresh directory","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"resources/packaging/linux/deb-source/prepare.py","lineNumber":28,"sourceCode":"import shutil\nimport subprocess\nimport sys\nimport tarfile\nimport tempfile\nimport tomllib\n\n\nROOT = Path(__file__).resolve().parents[4]\nDEBIAN = Path(__file__).resolve().parent / \"debian\"\n\n\ndef run(*args, cwd=ROOT, **kwargs):\n    return subprocess.run(args, cwd=cwd, check=True, **kwargs)\n\n\ndef prepare(output):\n    if output.exists() and any(output.iterdir()):\n        raise SystemExit(f\"Refusing to overwrite an existing release in {output}; use --output with a fresh directory\")\n    # Stage outside the checkout so Cargo cannot inherit a newer parent workspace.\n    with tempfile.TemporaryDirectory(prefix=\"sniffnet-debian-\") as staging:\n        source = prepare_staged(Path(staging))\n        output.mkdir(parents=True, exist_ok=True)\n        for path in Path(staging).iterdir():\n            shutil.move(str(path), output / path.name)\n    print(f\"Release files: {output}\", flush=True)\n    return output / source.name\n\n\ndef prepare_staged(output):\n    changelog = (DEBIAN / \"changelog\").read_text()\n    match = re.match(r\"sniffnet \\(([^)]+)\\) ([\\w-]+);\", changelog)\n    if not match:\n        raise SystemExit(\"Cannot parse debian/changelog\")\n    version = match[1].rsplit(\"-\", 1)[0]\n    tag = f\"refs/tags/v{version}\"\n    commit = run(\"git\", \"rev-parse\", \"--verify\", f\"{tag}^{{commit}}\",","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/GyulyVGC/sniffnet/blob/592a62a5ad2fb2e9f8470a6174ab9f18dc86997a/resources/packaging/linux/deb-source/prepare.py#L10-L46","documentation":"prepare() refuses to build a Debian source release into an --output directory that already exists and contains files. This guard prevents silently mixing a new release with stale artifacts from a previous run (or clobbering files the user wants kept). It aborts before any staging work so no partial output is written.","triggerScenarios":"Running prepare.py with --output pointing at a directory that exists and is non-empty; most commonly re-running the script with the same (default target/debian-source) output directory after a previous successful or partial run.","commonSituations":"Re-running the packager after a failed build left artifacts behind; running twice for the same version; pointing --output at a shared or pre-created release directory; forgetting that the default output dir persists between runs.","solutions":["Delete or empty the output directory (rm -rf target/debian-source) and re-run","Pass --output with a fresh, non-existent or empty directory path","If the previous run's artifacts are wanted, move them aside before re-running"],"exampleFix":"// before\npython3 prepare.py\n# after\nrm -rf target/debian-source && python3 prepare.py\n# or\npython3 prepare.py --output /tmp/deb-out-v1.3.1","handlingStrategy":"validation","validationCode":"from pathlib import Path\noutput = Path(args.output).resolve()\nif output.exists() and any(output.iterdir()):\n    raise SystemExit(f\"Output directory {output} is not empty; choose a fresh --output\")","typeGuard":"def is_fresh_output_dir(p: Path) -> bool:\n    return not p.exists() or not any(p.iterdir())","tryCatchPattern":"try:\n    prepare(output)\nexcept SystemExit as e:\n    print(f\"Packaging aborted: {e}\", file=sys.stderr)\n    sys.exit(2)","preventionTips":["Always invoke with a fresh --output path per release version","Add a pre-run cleanup step (rm -rf target/debian-source) in CI scripts","Never reuse the default output directory across versions","Check the directory contents before running if resuming an interrupted build"],"tags":["filesystem","file-already-exists","cli","packaging"],"backgroundTag":"file-already-exists","analyzedSha":"592a62a5ad2fb2e9f8470a6174ab9f18dc86997a","analyzedAt":"2026-09-18T11:20:14.290Z","contentChangedAt":"2026-09-18T11:20:14.290Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}