7 Commits
Author SHA1 Message Date
xixu-me e6f81ab68b Bump version to 1.2.8
CI/CD / test (macos-latest, 3.12) (push) Waiting to run
CI/CD / test (macos-latest, 3.13) (push) Waiting to run
CI/CD / test (ubuntu-latest, 3.12) (push) Waiting to run
CI/CD / test (ubuntu-latest, 3.13) (push) Waiting to run
CI/CD / test (windows-latest, 3.12) (push) Waiting to run
CI/CD / test (windows-latest, 3.13) (push) Waiting to run
Update the package version from 1.2.7 to 1.2.8 in preparation for a new release.
2025-06-15 16:22:19 +08:00
xixu-me 0a827ec260 Normalize archive path in CLI output
Introduces a helper to ensure the archive path shown in CLI output matches the final file created, mirroring the extension logic from core.py. This improves user clarity by displaying the correct archive filename before and after creation.
2025-06-15 15:17:10 +08:00
xixu-me 3645979315 Bump version to 1.2.7
CI/CD / test (macos-latest, 3.12) (push) Waiting to run
CI/CD / test (macos-latest, 3.13) (push) Waiting to run
CI/CD / test (ubuntu-latest, 3.12) (push) Waiting to run
CI/CD / test (ubuntu-latest, 3.13) (push) Waiting to run
CI/CD / test (windows-latest, 3.12) (push) Waiting to run
CI/CD / test (windows-latest, 3.13) (push) Waiting to run
Update the __version__ variable in __init__.py to 1.2.7 to reflect the new release.
2025-06-10 21:34:16 +08:00
xixu-me 3d85da8267 Add cross-platform file move utility for extraction
Introduced _move_file_cross_platform to handle file moves across drives, especially on Windows where rename may fail. Updated archive extraction logic to use this utility, ensuring robust file operations during extraction and conflict resolution.
2025-06-10 20:04:58 +08:00
xixu-me 4e87976fde Bump version to 1.2.6
Updated the __version__ variable in __init__.py to reflect the new release version 1.2.6.
2025-06-10 18:56:30 +08:00
xixu-me 372ad5d653 Update binary filenames in docs and READMEs
Standardized the naming convention for downloadable binaries across all documentation and translated README files. The new format uses 'tzst-{version}-{platform}-{arch}.zip' (e.g., 'tzst-{version}-linux-amd64.zip') for all platforms and architectures, replacing the previous inconsistent patterns.
2025-06-10 18:27:37 +08:00
xixu-me ffa12db17b Update CI workflow for architecture and naming consistency
Replaced 'x86_64' and 'aarch64' with 'amd64' and 'arm64' for consistency in architecture naming. Updated macOS 'os_name' to 'darwin' and removed 'v' prefix from artifact filenames to standardize naming conventions. Adjusted related conditions and paths in the workflow.
2025-06-10 15:18:19 +08:00
16 changed files with 139 additions and 93 deletions

No files matched your search

+12 -12
View File
@@ -123,11 +123,11 @@ jobs:
# Linux architectures # Linux architectures
- os: ubuntu-latest - os: ubuntu-latest
os_name: linux os_name: linux
arch: x86_64 arch: amd64
python-version: "3.12" python-version: "3.12"
- os: ubuntu-latest - os: ubuntu-latest
os_name: linux os_name: linux
arch: aarch64 arch: arm64
python-version: "3.12" python-version: "3.12"
cross_compile: true cross_compile: true
# Windows architectures # Windows architectures
@@ -142,11 +142,11 @@ jobs:
cross_compile: true cross_compile: true
# macOS architectures # macOS architectures
- os: macos-13 # Intel-based runner - os: macos-13 # Intel-based runner
os_name: macos os_name: darwin
arch: x86_64 arch: amd64
python-version: "3.12" python-version: "3.12"
- os: macos-14 # ARM-based runner (M1/M2) - os: macos-14 # ARM-based runner (M1/M2)
os_name: macos os_name: darwin
arch: arm64 arch: arm64
python-version: "3.12" python-version: "3.12"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -204,13 +204,13 @@ jobs:
python -m PyInstaller --onefile --name tzst --console --target-arch arm64 --icon docs/_static/favicon.ico src/main.py python -m PyInstaller --onefile --name tzst --console --target-arch arm64 --icon docs/_static/favicon.ico src/main.py
- name: Setup cross-compilation for Linux ARM64 - name: Setup cross-compilation for Linux ARM64
if: matrix.os == 'ubuntu-latest' && matrix.arch == 'aarch64' if: matrix.os == 'ubuntu-latest' && matrix.arch == 'arm64'
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu sudo apt-get install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
- name: Build binary for ARM64 on Linux - name: Build binary for ARM64 on Linux
if: matrix.os == 'ubuntu-latest' && matrix.arch == 'aarch64' if: matrix.os == 'ubuntu-latest' && matrix.arch == 'arm64'
env: env:
CC: aarch64-linux-gnu-gcc CC: aarch64-linux-gnu-gcc
run: | run: |
@@ -236,19 +236,19 @@ jobs:
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
run: | run: |
cd archive cd archive
zip -r ../tzst-v${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip . zip -r ../tzst-${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip .
- name: Create zip archive (Windows) - name: Create zip archive (Windows)
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
run: | run: |
cd archive cd archive
Compress-Archive -Path * -DestinationPath ../tzst-v${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip Compress-Archive -Path * -DestinationPath ../tzst-${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip
- name: Upload binary artifacts - name: Upload binary artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: binary-${{ matrix.os_name }}-${{ matrix.arch }} name: binary-${{ matrix.os_name }}-${{ matrix.arch }}
path: tzst-v${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip path: tzst-${{ steps.version.outputs.version }}-${{ matrix.os_name }}-${{ matrix.arch }}.zip
create-release: create-release:
needs: [publish, build-binaries] needs: [publish, build-binaries]
@@ -282,10 +282,10 @@ jobs:
- name: Upload Release Assets - name: Upload Release Assets
run: | run: |
echo "Available files:" echo "Available files:"
ls -la tzst-v${{ steps.version.outputs.version }}-*.zip 2>/dev/null || echo "No zip files found" ls -la tzst-${{ steps.version.outputs.version }}-*.zip 2>/dev/null || echo "No zip files found"
success=0 success=0
for file in tzst-v${{ steps.version.outputs.version }}-*.zip; do for file in tzst-${{ steps.version.outputs.version }}-*.zip; do
if [ -f "$file" ]; then if [ -f "$file" ]; then
echo "Uploading $file" echo "Uploading $file"
if gh release upload ${{ github.ref_name }} "$file" --clobber; then if gh release upload ${{ github.ref_name }} "$file" --clobber; then
+6 -6
View File
@@ -40,12 +40,12 @@
| المنصة | المعمارية | الملف | | المنصة | المعمارية | الملف |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{version}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{version}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{version}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{version}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{version}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{version}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
#### 🛠️ خطوات التثبيت #### 🛠️ خطوات التثبيت
+6 -6
View File
@@ -38,12 +38,12 @@ Lade eigenständige ausführbare Dateien herunter, die keine Python-Installation
| Plattform | Architektur | Datei | | Plattform | Architektur | Datei |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{Version}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{Version}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{Version}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{Version}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{Version}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{Version}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
#### 🛠️ Installationsschritte #### 🛠️ Installationsschritte
+6 -6
View File
@@ -38,12 +38,12 @@ Descarga ejecutables independientes que no requieren instalación de Python:
| Plataforma | Arquitectura | Archivo | | Plataforma | Arquitectura | Archivo |
|--------------|---------------|---------------------------------------| |--------------|---------------|---------------------------------------|
| **🐧 Linux** | x86_64 | `tzst-v{versión}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{versión}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{versión}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{versión}-linux-arm64.zip` |
| **🪟 Windows**| x64 | `tzst-v{versión}-windows-amd64.zip` | | **🪟 Windows**| x64 | `tzst-{versión}-windows-amd64.zip` |
| **🪟 Windows**| ARM64 | `tzst-v{versión}-windows-arm64.zip` | | **🪟 Windows**| ARM64 | `tzst-{versión}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{versión}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{versión}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{versión}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{versión}-darwin-arm64.zip` |
#### 🛠️ Pasos de Instalación #### 🛠️ Pasos de Instalación
+6 -6
View File
@@ -38,12 +38,12 @@ Téléchargez des exécutables autonomes qui ne nécessitent pas d'installation
| Plateforme | Architecture | Fichier | | Plateforme | Architecture | Fichier |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{version}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{version}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{version}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{version}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{version}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{version}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
#### 🛠️ Étapes d'installation #### 🛠️ Étapes d'installation
+6 -6
View File
@@ -38,12 +38,12 @@ Python インストール不要のスタンドアロン実行ファイルをダ
| プラットフォーム | アーキテクチャ | ファイル | | プラットフォーム | アーキテクチャ | ファイル |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{バージョン}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{バージョン}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{バージョン}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{バージョン}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{バージョン}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{バージョン}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{バージョン}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{バージョン}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{バージョン}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{バージョン}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{バージョン}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{バージョン}-darwin-arm64.zip` |
#### 🛠️ インストール手順 #### 🛠️ インストール手順
+6 -6
View File
@@ -38,12 +38,12 @@ Python 설치가 필요 없는 독립형 실행 파일 다운로드:
| 플랫폼 | 아키텍처 | 파일 | | 플랫폼 | 아키텍처 | 파일 |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{버전}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{버전}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{버전}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{버전}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{버전}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{버전}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{버전}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{버전}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{버전}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{버전}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{버전}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{버전}-darwin-arm64.zip` |
#### 🛠️ 설치 단계 #### 🛠️ 설치 단계
+6 -6
View File
@@ -38,12 +38,12 @@ Download standalone executables that don't require Python installation:
| Platform | Architecture | File | | Platform | Architecture | File |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{version}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{version}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{version}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{version}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{version}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{version}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
#### 🛠️ Installation Steps #### 🛠️ Installation Steps
+6 -6
View File
@@ -38,12 +38,12 @@ Baixe executáveis independentes que não requerem instalação do Python:
| Plataforma | Arquitetura | Arquivo | | Plataforma | Arquitetura | Arquivo |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{versão}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{versão}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{versão}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{versão}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{versão}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{versão}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{versão}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{versão}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{versão}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{versão}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{versão}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{versão}-darwin-arm64.zip` |
#### 🛠️ Passos de Instalação #### 🛠️ Passos de Instalação
+6 -6
View File
@@ -38,12 +38,12 @@
| Платформа | Архитектура | Файл | | Платформа | Архитектура | Файл |
|----------|-------------|------| |----------|-------------|------|
| **🐧 Linux** | x86_64 | `tzst-v{версия}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{версия}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{версия}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{версия}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{версия}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{версия}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{версия}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{версия}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{версия}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{версия}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{версия}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{версия}-darwin-arm64.zip` |
#### 🛠️ Шаги установки #### 🛠️ Шаги установки
+6 -6
View File
@@ -38,12 +38,12 @@
| 平台 | 架构 | 文件 | | 平台 | 架构 | 文件 |
|------|------|------| |------|------|------|
| **🐧 Linux** | x86_64 | `tzst-v{版本}-linux-x86_64.zip` | | **🐧 Linux** | x86_64 | `tzst-{版本}-linux-amd64.zip` |
| **🐧 Linux** | ARM64 | `tzst-v{版本}-linux-aarch64.zip` | | **🐧 Linux** | ARM64 | `tzst-{版本}-linux-arm64.zip` |
| **🪟 Windows** | x64 | `tzst-v{版本}-windows-amd64.zip` | | **🪟 Windows** | x64 | `tzst-{版本}-windows-amd64.zip` |
| **🪟 Windows** | ARM64 | `tzst-v{版本}-windows-arm64.zip` | | **🪟 Windows** | ARM64 | `tzst-{版本}-windows-arm64.zip` |
| **🍎 macOS** | Intel | `tzst-v{版本}-macos-x86_64.zip` | | **🍎 macOS** | Intel | `tzst-{版本}-darwin-amd64.zip` |
| **🍎 macOS** | Apple Silicon | `tzst-v{版本}-macos-arm64.zip` | | **🍎 macOS** | Apple Silicon | `tzst-{版本}-darwin-arm64.zip` |
#### 🛠️ 安装步骤 #### 🛠️ 安装步骤
+6 -6
View File
@@ -115,12 +115,12 @@ Download platform-specific standalone executables from [GitHub Releases](https:/
| Platform | Architecture | File | | Platform | Architecture | File |
|----------|-------------|------| |----------|-------------|------|
| **Linux** | x86_64 | `tzst-v{version}-linux-x86_64.zip` | | **Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **Linux** | ARM64 | `tzst-v{version}-linux-aarch64.zip` | | **Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **Windows** | x64 | `tzst-v{version}-windows-amd64.zip` | | **Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **Windows** | ARM64 | `tzst-v{version}-windows-arm64.zip` | | **Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **macOS** | Intel | `tzst-v{version}-macos-x86_64.zip` | | **macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **macOS** | Apple Silicon | `tzst-v{version}-macos-arm64.zip` | | **macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
#### Installation Steps #### Installation Steps
+6 -6
View File
@@ -36,12 +36,12 @@ Download the appropriate executable from [GitHub Releases](https://github.com/xi
| Platform | Architecture | Download | | Platform | Architecture | Download |
|----------|--------------|----------| |----------|--------------|----------|
| **Linux** | x86_64 | `tzst-v{version}-linux-x86_64.zip` | | **Linux** | x86_64 | `tzst-{version}-linux-amd64.zip` |
| **Linux** | ARM64 | `tzst-v{version}-linux-aarch64.zip` | | **Linux** | ARM64 | `tzst-{version}-linux-arm64.zip` |
| **Windows** | x64 | `tzst-v{version}-windows-amd64.zip` | | **Windows** | x64 | `tzst-{version}-windows-amd64.zip` |
| **Windows** | ARM64 | `tzst-v{version}-windows-arm64.zip` | | **Windows** | ARM64 | `tzst-{version}-windows-arm64.zip` |
| **macOS** | Intel | `tzst-v{version}-macos-x86_64.zip` | | **macOS** | Intel | `tzst-{version}-darwin-amd64.zip` |
| **macOS** | Apple Silicon | `tzst-v{version}-macos-arm64.zip` | | **macOS** | Apple Silicon | `tzst-{version}-darwin-arm64.zip` |
Extract the archive and add the executable to your PATH. Extract the archive and add the executable to your PATH.
+1 -1
View File
@@ -4,7 +4,7 @@ Leveraging cutting-edge Zstandard compression to deliver superior performance,
security, and reliability. security, and reliability.
""" """
__version__ = "1.2.5" __version__ = "1.2.8"
from .core import ( from .core import (
TzstArchive, TzstArchive,
+30 -2
View File
@@ -16,6 +16,31 @@ from .core import (
from .exceptions import TzstArchiveError, TzstDecompressionError from .exceptions import TzstArchiveError, TzstDecompressionError
def _normalize_archive_path(archive_path: Path) -> Path:
"""Normalize archive path by ensuring correct extension.
This exactly mirrors the logic in core.py's create_archive function to show
the correct final path in CLI output.
Args:
archive_path: Input archive path
Returns:
Path: Normalized path with correct extension
"""
# Convert to Path if it's not already
archive_path = Path(archive_path)
# Ensure archive has correct extension - this logic exactly matches core.py
if archive_path.suffix.lower() not in [".tzst", ".zst"]:
if archive_path.suffix.lower() == ".tar":
archive_path = archive_path.with_suffix(".tar.zst")
else:
archive_path = archive_path.with_suffix(archive_path.suffix + ".tzst")
return archive_path
def _interactive_conflict_callback(target_path: Path) -> ConflictResolution: def _interactive_conflict_callback(target_path: Path) -> ConflictResolution:
"""Interactive callback for handling file conflicts in CLI. """Interactive callback for handling file conflicts in CLI.
@@ -219,14 +244,17 @@ def _execute_archive_creation(
Returns: Returns:
int: Exit code (0 for success, non-zero for failure) int: Exit code (0 for success, non-zero for failure)
""" """
print(f"Creating archive: {archive_path}") # Normalize archive path to show the correct final filename
normalized_archive_path = _normalize_archive_path(archive_path)
print(f"Creating archive: {normalized_archive_path}")
for file_path in files: for file_path in files:
print(f" Adding: {file_path}") print(f" Adding: {file_path}")
# Use atomic file operations by default for better reliability # Use atomic file operations by default for better reliability
# This creates the archive in a temporary file first, then moves it # This creates the archive in a temporary file first, then moves it
create_archive(archive_path, files, compression_level, use_temp_file=use_temp_file) create_archive(archive_path, files, compression_level, use_temp_file=use_temp_file)
print(f"Archive created successfully - {archive_path}") print(f"Archive created successfully - {normalized_archive_path}")
return 0 return 0
+24 -6
View File
@@ -87,6 +87,24 @@ def _get_unique_filename(file_path: Path) -> Path:
counter += 1 counter += 1
def _move_file_cross_platform(src: Path, dst: Path) -> None:
"""Move a file from src to dst, handling cross-drive moves on Windows."""
try:
# Try the fast rename operation first
src.rename(dst)
except OSError as e:
# On Windows, rename fails across drives with error 17
# Fall back to copy + delete for cross-drive moves
import shutil
try:
shutil.copy2(src, dst)
src.unlink()
except Exception:
# If copy also fails, re-raise the original rename error
raise e from None
def _handle_file_conflict( def _handle_file_conflict(
target_path: Path, target_path: Path,
resolution: ConflictResolution | str, resolution: ConflictResolution | str,
@@ -845,15 +863,14 @@ def extract_archive(
): ):
continue continue
elif actual_resolution == ConflictResolution.EXIT: elif actual_resolution == ConflictResolution.EXIT:
break break # For AUTO_RENAME, we need to adjust the member path
# For AUTO_RENAME, we need to adjust the member path
if actual_resolution in ( if actual_resolution in (
ConflictResolution.AUTO_RENAME, ConflictResolution.AUTO_RENAME,
ConflictResolution.AUTO_RENAME_ALL, ConflictResolution.AUTO_RENAME_ALL,
): ):
# Create parent directories for renamed file # Create parent directories for renamed file
final_path.parent.mkdir(parents=True, exist_ok=True) if final_path:
final_path.parent.mkdir(parents=True, exist_ok=True)
# Extract to temporary location, then move # Extract to temporary location, then move
temp_extract_path = Path(tempfile.mkdtemp()) temp_extract_path = Path(tempfile.mkdtemp())
try: try:
@@ -861,7 +878,8 @@ def extract_archive(
member, temp_extract_path, filter=filter member, temp_extract_path, filter=filter
) )
temp_file = temp_extract_path / member temp_file = temp_extract_path / member
temp_file.rename(final_path) if final_path:
_move_file_cross_platform(temp_file, final_path)
finally: finally:
# Clean up temp directory # Clean up temp directory
import shutil import shutil
@@ -920,7 +938,7 @@ def extract_archive(
target_path.unlink() # Remove existing file target_path.unlink() # Remove existing file
if target_path: if target_path:
temp_file.rename(target_path) _move_file_cross_platform(temp_file, target_path)
finally: finally:
# Clean up temp directory # Clean up temp directory
import shutil import shutil