Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/package-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ permissions: {}

jobs:
package-macos:
runs-on: macos-12
runs-on: macos-13
strategy:
matrix:
setup:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12, windows-2019]
os: [macos-13, windows-2019]
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
Expand Down
127 changes: 59 additions & 68 deletions .github/workflows/package-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ jobs:
runs-on: windows-2019
strategy:
matrix:
type:
- store-app
- signed-app
- installer
- portable
setup:
- type: installer
- type: portable
build-portable: 1
- type: store-app
disable-autoupdate: 1
fail-fast: false
env:
CODESIGN: 0
CODESIGN: ${{ !!secrets.AZURE_CERT_PROFILE_NAME }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -32,9 +33,6 @@ jobs:
-DiscidVersion $Env:DISCID_VERSION -DiscidSha256Sum $Env:DISCID_SHA256SUM `
-FpcalcVersion $Env:FPCALC_VERSION -FpcalcSha256Sum $Env:FPCALC_SHA256SUM
Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64"
$ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD)
$BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD")
Add-Content $env:GITHUB_ENV "BUILD_NUMBER=$BuildNumber"
New-Item -Name .\artifacts -ItemType Directory
env:
DISCID_VERSION: 0.6.4
Expand All @@ -57,80 +55,73 @@ jobs:
- name: Patch build version
if: startsWith(github.ref, 'refs/tags/') != true
run: |
$ReleaseTag = $(git describe --match "release-*" --abbrev=0 --always HEAD)
$BuildNumber = $(git rev-list --count "$ReleaseTag..HEAD")
python setup.py patch_version --platform=$Env:BUILD_NUMBER.$(git rev-parse --short HEAD)
- name: Run tests
timeout-minutes: 30
run: pytest --verbose
- name: Prepare code signing certificate
if: matrix.type != 'store-app'
- name: Prepare clean build environment
run: |
If ($Env:CODESIGN_P12_URL -And $Env:AWS_ACCESS_KEY_ID) {
pip install awscli
aws s3 cp "$Env:CODESIGN_P12_URL" .\codesign.pfx
Add-Content $env:GITHUB_ENV "CODESIGN=1"
} Else {
Write-Output "::warning::No code signing certificate available, skipping code signing."
}
env:
AWS_DEFAULT_REGION: eu-central-1
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
CODESIGN_P12_URL: ${{ secrets.CODESIGN_P12_URL }}
- name: Build Windows 10 store app package
if: matrix.type == 'store-app'
Remove-Item -Path build,dist/picard,locale -Recurse -ErrorAction Ignore
python setup.py clean
- name: Build
run: |
& .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER
Move-Item .\dist\*.msix .\artifacts
python setup.py build --build-number=$BuildNumber
python setup.py build_ext
pyinstaller --noconfirm --clean picard.spec
If ($env:PICARD_BUILD_PORTABLE -ne "1") {
dist\picard\_internal\fpcalc -version
}
env:
PICARD_APPX_PUBLISHER: CN=0A9169B7-05A3-4ED9-8876-830F17846709
- name: Build Windows 10 signed app package
if: matrix.type == 'signed-app' && env.CODESIGN == '1'
run: |
$CertificateFile = ".\codesign.pfx"
$CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText
& .\scripts\package\win-package-appx.ps1 -BuildNumber $Env:BUILD_NUMBER `
-CertificateFile $CertificateFile -CertificatePassword $CertificatePassword
Move-Item .\dist\*.msix .\artifacts
env:
CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }}
PICARD_BUILD_PORTABLE: ${{ matrix.setup.build-portable }}
PICARD_DISABLE_AUTOUPDATE: ${{ matrix.setup.disable-autoupdate }}
- name: Sign picard.exe
uses: azure/trusted-signing-action@v0.5.0
if: matrix.setup.type != 'portable' && env.CODESIGN == 'true'
with:
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
endpoint: ${{ secrets.AZURE_ENDPOINT }}
trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }}
certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }}
files-folder: dist\picard
files-folder-filter: exe
files-folder-recurse: true
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Build Windows installer
if: matrix.type == 'installer'
if: matrix.setup.type == 'installer'
run: |
# choco install nsis
If ($Env:CODESIGN -eq "1") {
$CertificateFile = ".\codesign.pfx"
$CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText
} Else {
$CertificateFile = $null
$CertificatePassword = $null
}
& .\scripts\package\win-package-installer.ps1 -BuildNumber $Env:BUILD_NUMBER `
-CertificateFile $CertificateFile -CertificatePassword $CertificatePassword
makensis.exe /INPUTCHARSET UTF8 installer\picard-setup.nsi
Move-Item .\installer\*.exe .\artifacts
dist\picard\_internal\fpcalc -version
env:
CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }}
- name: Build Windows portable app
if: matrix.type == 'portable'
if: matrix.setup.type == 'portable'
run: |
If ($Env:CODESIGN -eq "1") {
$CertificateFile = ".\codesign.pfx"
$CertificatePassword = ConvertTo-SecureString -String $Env:CODESIGN_P12_PASSWORD -Force -AsPlainText
} Else {
$CertificateFile = $null
$CertificatePassword = $null
}
& .\scripts\package\win-package-portable.ps1 -BuildNumber $Env:BUILD_NUMBER `
-CertificateFile $CertificateFile -CertificatePassword $CertificatePassword
Move-Item .\dist\*.exe .\artifacts
env:
CODESIGN_P12_PASSWORD: ${{ secrets.CODESIGN_P12_PASSWORD }}
- name: Cleanup
if: env.CODESIGN == '1'
run: Remove-Item .\codesign.pfx
- name: Build Windows 10 store app package
if: matrix.setup.type == 'store-app'
run: |
& .\scripts\package\win-package-appx.ps1 dist\picard
Move-Item .\dist\*.msix .\artifacts
- name: Sign final executable
uses: azure/trusted-signing-action@v0.5.0
if: matrix.setup.type != 'store-app' && env.CODESIGN == 'true'
with:
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
endpoint: ${{ secrets.AZURE_ENDPOINT }}
trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }}
certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }}
files-folder: artifacts
files-folder-filter: exe
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Archive production artifacts
uses: actions/upload-artifact@v4
if: matrix.type != 'signed-app' || env.CODESIGN == '1'
with:
name: windows-${{ matrix.type }}
name: windows-${{ matrix.setup.type }}
path: artifacts/
6 changes: 3 additions & 3 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, ubuntu-latest, windows-2019]
os: [macos-13, ubuntu-latest, windows-2019]
python-version: ['3.9', '3.10', '3.11', '3.12']
include:
- os: macos-12
- os: macos-13
python-version: '3.9'
env:
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-12, ubuntu-latest, windows-latest]
os: [macos-13, ubuntu-latest, windows-latest]
python-version: ['3.9', '3.12']

steps:
Expand Down
2 changes: 1 addition & 1 deletion picard/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ def make_filename(self, filename, metadata, settings=None, naming_format=None):
new_filename = self._format_filename(new_dirname, new_filename, metadata, settings, naming_format)

new_path = os.path.join(new_dirname, new_filename)
return normpath(new_path)
return normpath(new_path, realpath=False)

def _rename(self, old_filename, metadata, settings=None):
new_filename = self.make_filename(old_filename, metadata, settings)
Expand Down
3 changes: 3 additions & 0 deletions picard/ui/metadatabox.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,9 @@ def _update_tags(self, new_selection=True, drop_album_caches=False):

tag_diff.add('~length', str(orig_metadata.length), str(new_metadata.length),
removable=False, readonly=True)
if (len(files) == 1):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code snippet looks good to me. However you can combine the two if statements as follows:

if (len(files) == 1) and (settings['rename_files'] or settings['move_files']):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok 👍

if settings['rename_files'] or settings['move_files']:
tag_diff.add('Path', [file.filename], [file.make_filename(file.filename, orig_metadata)], removable=False, readonly=True)

for track in tracks:
if track.num_linked_files == 0:
Expand Down
2 changes: 1 addition & 1 deletion picard/ui/scripteditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def _example_to_filename(self, file):
if not self.settings['move_files']:
return os.path.basename(filename_before), os.path.basename(filename_after)
return filename_before, filename_after
except (ScriptError, TypeError, WinPathTooLong):
except (FileNotFoundError, PermissionError, ScriptError, TypeError, WinPathTooLong):
return "", ""

def update_example_listboxes(self, before_listbox, after_listbox):
Expand Down
21 changes: 11 additions & 10 deletions picard/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Copyright (C) 2004 Robert Kaye
# Copyright (C) 2006-2009, 2011-2012, 2014 Lukáš Lalinský
# Copyright (C) 2008-2011, 2014, 2018-2023 Philipp Wolfer
# Copyright (C) 2008-2011, 2014, 2018-2024 Philipp Wolfer
# Copyright (C) 2009 Carlin Mangar
# Copyright (C) 2009 david
# Copyright (C) 2010 fatih
Expand Down Expand Up @@ -232,15 +232,16 @@ def system_supports_long_paths():
return False


def normpath(path):
def normpath(path, realpath=True):
path = os.path.normpath(path)
try:
path = os.path.realpath(path)
except OSError as why:
# realpath can fail if path does not exist or is not accessible
# or on Windows if drives are mounted without mount manager
# (see https://tickets.metabrainz.org/browse/PICARD-2425).
log.warning("Failed getting realpath for `%s`: %s", path, why)
if realpath:
try:
path = os.path.realpath(path)
except OSError as why:
# realpath can fail if path does not exist or is not accessible
# or on Windows if drives are mounted without mount manager
# (see https://tickets.metabrainz.org/browse/PICARD-2425).
log.warning("Failed getting realpath for `%s`: %s", path, why)
# If the path is longer than 259 characters on Windows, prepend the \\?\
# prefix. This enables access to long paths using the Windows API. See
# https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
Expand Down Expand Up @@ -946,7 +947,7 @@ def extract_year_from_date(dt):
return int(dt.get('year'))
else:
return parse(dt).year
except (TypeError, ValueError):
except (OverflowError, TypeError, ValueError):
return None


Expand Down
22 changes: 15 additions & 7 deletions picard/util/filenaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from enum import IntEnum
import math
import os
from pathlib import Path
import re
import shutil
import struct
Expand Down Expand Up @@ -326,14 +327,21 @@ def _get_filename_limit(target):
limit = limits[target]
except KeyError:
# we need to call statvfs on an existing target
d = target
while not os.path.exists(d):
d = os.path.dirname(d)
p = Path(target)
while not p.exists():
p = p.parent
# XXX http://bugs.python.org/issue18695
try:
limit = os.statvfs(d).f_namemax
except UnicodeEncodeError:
limit = os.statvfs(d.encode(_io_encoding)).f_namemax
limit = 0
while not limit:
try:
try:
limit = os.statvfs(p).f_namemax
except UnicodeEncodeError:
limit = os.statvfs(str(p).encode(_io_encoding)).f_namemax
except (FileNotFoundError, PermissionError):
if p == p.parent: # we reached the root
raise
p = p.parent
limits[target] = limit
return limit

Expand Down
Loading
Loading