Skip to content

Commit 4da62fa

Browse files
committed
feat: Release v4.2.0 with intelligent defaults and performance optimizations
BREAKING CHANGES: - Enable -Recursive mode by default for automatic nested dependency processing - Enable -EnableTagSorting by default for intelligent tag temporal sorting New Features: - Intelligent tag selection algorithm prioritizing specified "Tag" values during conflicts - Performance-optimized tag sorting that only runs during API compatibility resolution - Enhanced repository conflict detection with clear status logging - Comprehensive debug logging for tag sorting operations and conflict resolution Performance Improvements: - On-demand tag date fetching only when conflicts require resolution - Optimized git operations using efficient `git for-each-ref` instead of multiple calls - Smart tag date caching during recursive processing - Reduced unnecessary sorting operations User Experience Enhancements: - Zero configuration required - optimal behavior out-of-the-box - Clear logging when repositories already exist in dictionary - Enhanced parameter documentation reflecting new defaults - Simplified mental model for new users Backward Compatibility: - All existing configurations work without modification - Legacy behavior available via `-Recursive:$false -EnableTagSorting:$false` - Graceful fallback for tag date fetching failures Documentation Updates: - Updated README.md with new default behavior examples - Enhanced API compatibility algorithm descriptions - Added performance optimization details - Updated troubleshooting for both legacy and modern modes - Comprehensive migration guide from v4.1.x to v4.2.0 Technical Changes: - Optimized Sort-TagsByDate function with context-aware processing - Enhanced Update-RepositoryDictionary with improved conflict resolution - Better PowerShell object handling for reliable sorting operations - Fixed string interpolation issues in datetime logging Testing: Extensive testing performed in both Strict and Permissive modes Closed #4
1 parent 2d5bd4e commit 4da62fa

File tree

3 files changed

+226
-124
lines changed

3 files changed

+226
-124
lines changed

CHANGELOG.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,54 @@ All notable changes to LsiGitCheckout will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [4.2.0] - 2025-01-16
8+
## [4.2.0] - 2025-01-17
99

1010
### Added
11-
- **Tag Temporal Sorting**: New `-EnableTagSorting` parameter enables automatic chronological tag ordering using actual git tag dates
12-
- Intelligent tag selection algorithm that prioritizes existing/new "Tag" values when resolving repository conflicts
11+
- **Default Intelligent Behavior**: Made `-Recursive` and `-EnableTagSorting` enabled by default for optimal out-of-the-box experience
12+
- **Performance-Optimized Tag Temporal Sorting**: Intelligent tag selection algorithm that prioritizes existing/new "Tag" values when resolving repository conflicts
1313
- `Get-GitTagDates` function for efficient tag date fetching using `git for-each-ref`
1414
- `Sort-TagsByDate` function for chronological tag sorting with comprehensive debug logging
1515
- Enhanced `Get-TagUnion` function with temporal sorting support when tag dates are available
1616
- Priority-based tag selection: prefers specified "Tag" values over other compatible tags when both are compatible
1717
- Fallback to chronologically most recent tag when neither existing nor new "Tag" is compatible
1818
- Comprehensive verbose and debug logging for tag temporal sorting operations
1919
- Tag date verification and temporal order display in verbose mode
20-
- Relaxed temporal ordering requirements when `-EnableTagSorting` is enabled
2120
- Tag date caching in repository dictionary for performance optimization
21+
- Enhanced repository conflict detection logging with clear status indicators
2222

2323
### Changed
24+
- **BREAKING (Default Behavior)**: `-Recursive` now defaults to `$true` (enabled by default)
25+
- **BREAKING (Default Behavior)**: `-EnableTagSorting` now defaults to `$true` (enabled by default)
2426
- Enhanced repository dictionary structure to include `TagDates` field for storing tag date mappings
2527
- Improved tag selection logic in all API compatibility scenarios (Strict-Strict, Strict-Permissive, Permissive-Permissive, Permissive-Strict)
2628
- Updated summary report to display tag temporal sorting status and statistics
2729
- Enhanced union algorithm to use temporal sorting when enabled, falling back to original logic when disabled
28-
- Improved error handling for tag date parsing and git command failures
30+
- Optimized tag sorting to only run when needed during API compatibility resolution
31+
- Improved repository conflict logging to clearly indicate when repositories already exist in dictionary
32+
- Enhanced error handling for tag date parsing and git command failures
2933

3034
### Fixed
3135
- PowerShell string interpolation issues with datetime formatting in log messages
3236
- Improved tag sorting object creation using `[PSCustomObject]` for reliable `Sort-Object` operations
3337
- Enhanced temporal verification logging with proper variable delimiting
3438

3539
### Performance
36-
- Minimal server impact: tag dates fetched only once per repository after initial checkout
40+
- **Optimized on-demand processing**: Tag dates fetched only when conflicts require resolution during recursive processing
3741
- Efficient `git for-each-ref` command usage instead of individual `git log` calls per tag
3842
- Tag date caching eliminates redundant git operations during recursive processing
43+
- Reduced unnecessary tag date fetching and sorting operations
3944

4045
### Backward Compatibility
46+
- **Behavior Change**: Default behavior now includes recursive processing and intelligent tag sorting
47+
- **Legacy Support**: Use `-Recursive:$false -EnableTagSorting:$false` to restore v4.1.x behavior
4148
- **Non-breaking**: All existing configurations work without modification
42-
- **Default behavior**: `-EnableTagSorting` is disabled by default, maintaining v4.1.x behavior
43-
- **Opt-in feature**: New functionality only active when explicitly enabled
44-
- Manual temporal ordering requirements preserved when tag sorting is disabled
49+
- Manual temporal ordering requirements preserved when tag sorting is explicitly disabled
50+
51+
### Migration Notes
52+
- **Zero configuration upgrade**: Most users get optimal behavior without any parameter changes
53+
- **Enhanced user experience**: New users get intelligent behavior by default
54+
- **Optional legacy mode**: Previous behavior available via explicit parameter flags
55+
- **Performance benefits**: Automatic optimization for complex dependency graphs
4556

4657
## [4.1.1] - 2025-01-16
4758

LsiGitCheckout.ps1

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,33 @@
2424
.PARAMETER Verbose
2525
Increases verbosity of output messages.
2626
.PARAMETER Recursive
27-
Enables recursive dependency discovery and processing.
27+
Enables recursive dependency discovery and processing. Enabled by default.
2828
.PARAMETER MaxDepth
2929
Maximum recursion depth for dependency discovery. Defaults to 5.
3030
.PARAMETER ApiCompatibility
3131
Default API compatibility mode when not specified in dependencies. Can be 'Strict' or 'Permissive'. Defaults to 'Permissive'.
3232
.PARAMETER EnableTagSorting
33-
Enables automatic tag temporal sorting using git tag dates. This removes the requirement for manual temporal ordering in "API Compatible Tags" and suppresses related warnings in Permissive mode.
33+
Enables automatic tag temporal sorting using git tag dates. This removes the requirement for manual temporal ordering in "API Compatible Tags" and provides intelligent tag selection. Enabled by default.
3434
.EXAMPLE
3535
.\LsiGitCheckout.ps1
3636
.\LsiGitCheckout.ps1 -InputFile "C:\configs\myrepos.json" -CredentialsFile "C:\configs\my_credentials.json"
3737
.\LsiGitCheckout.ps1 -Recursive -MaxDepth 10
3838
.\LsiGitCheckout.ps1 -InputFile "repos.json" -EnableDebug -Recursive -ApiCompatibility Strict
3939
.\LsiGitCheckout.ps1 -Recursive -EnableTagSorting -Verbose
4040
.NOTES
41-
Version: 4.2.0-dev
42-
Last Modified: 2025-01-16
41+
Version: 4.2.0
42+
Last Modified: 2025-01-17
4343
4444
This script uses PuTTY/plink for SSH authentication. SSH keys must be in PuTTY format (.ppk).
4545
Use PuTTYgen to convert OpenSSH keys to PuTTY format if needed.
4646
47+
Changes in 4.2.0:
48+
- Made -Recursive and -EnableTagSorting default (enabled by default)
49+
- Optimized tag sorting to only run when needed during API compatibility resolution
50+
- Improved logging to clearly indicate when repositories already exist in dictionary
51+
- Enhanced repository conflict detection messaging
52+
- Reduced unnecessary tag date fetching and sorting operations
53+
4754
Changes in 4.2.0-dev:
4855
- Added -EnableTagSorting parameter for automatic tag temporal sorting
4956
- Added tag date fetching functionality after repository checkout
@@ -114,7 +121,7 @@ param(
114121
[switch]$EnableDebug,
115122

116123
[Parameter()]
117-
[switch]$Recursive,
124+
[switch]$Recursive = $true,
118125

119126
[Parameter()]
120127
[int]$MaxDepth = 5,
@@ -124,11 +131,11 @@ param(
124131
[string]$ApiCompatibility = 'Permissive',
125132

126133
[Parameter()]
127-
[switch]$EnableTagSorting
134+
[switch]$EnableTagSorting = $true
128135
)
129136

130137
# Script configuration
131-
$script:Version = "4.2.0-dev"
138+
$script:Version = "4.2.0"
132139
$script:ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
133140
$script:ErrorFile = Join-Path $ScriptPath "LsiGitCheckout_Errors.txt"
134141
$script:DebugLogFile = Join-Path $ScriptPath ("debug_log_{0}.txt" -f (Get-Date -Format "yyyyMMddHHmm"))
@@ -460,14 +467,17 @@ function Sort-TagsByDate {
460467
param(
461468
[array]$Tags,
462469
[hashtable]$TagDates,
463-
[string]$RepositoryUrl
470+
[string]$RepositoryUrl,
471+
[string]$Context = "compatibility resolution"
464472
)
465473

466474
if (-not $script:EnableTagSorting -or $TagDates.Count -eq 0) {
467-
Write-Log "Tag sorting disabled or no tag dates available, returning tags in original order" -Level Debug
475+
Write-Log "Tag sorting disabled or no tag dates available for $Context, returning tags in original order" -Level Debug
468476
return $Tags
469477
}
470478

479+
Write-Log "Performing tag temporal sorting for $Context on repository: $RepositoryUrl" -Level Debug
480+
471481
# Separate tags that have dates from those that don't
472482
$tagsWithDates = @()
473483
$tagsWithoutDates = @()
@@ -493,7 +503,7 @@ function Sort-TagsByDate {
493503

494504
# Only show verbose output for temporal sorting results
495505
if ($VerbosePreference -eq 'Continue') {
496-
Write-Log "Tag temporal sorting for $RepositoryUrl :" -Level Verbose
506+
Write-Log "Tag temporal sorting for $RepositoryUrl ($Context):" -Level Verbose
497507
Write-Log " Original: $($Tags -join ', ')" -Level Verbose
498508
Write-Log " Temporal: $($sortedTags -join ', ')" -Level Verbose
499509
}
@@ -646,7 +656,7 @@ function Get-TagUnion {
646656
}
647657

648658
$allTags = @($unionSet.Keys)
649-
$sortedUnion = Sort-TagsByDate -Tags $allTags -TagDates $TagDates -RepositoryUrl $RepositoryUrl
659+
$sortedUnion = Sort-TagsByDate -Tags $allTags -TagDates $TagDates -RepositoryUrl $RepositoryUrl -Context "union calculation"
650660

651661
Write-Log "Temporal union result: $($sortedUnion -join ', ')" -Level Debug
652662
return $sortedUnion
@@ -748,6 +758,8 @@ function Update-RepositoryDictionary {
748758

749759
if ($script:RepositoryDictionary.ContainsKey($repoUrl)) {
750760
# Repository already exists, check compatibility
761+
Write-Log "Repository already exists in dictionary, performing API compatibility check..." -Level Info
762+
751763
$existingRepo = $script:RepositoryDictionary[$repoUrl]
752764
$existingAbsolutePath = $existingRepo.AbsolutePath
753765

@@ -759,11 +771,11 @@ function Update-RepositoryDictionary {
759771
throw $errorMessage
760772
}
761773

762-
# Get tag dates if available
774+
# Get tag dates if available (only fetch if we need them for sorting)
763775
$tagDates = if ($existingRepo.ContainsKey('TagDates')) { $existingRepo.TagDates } else { @{} }
764776

765777
# Create ordered tag lists (API Compatible Tags + Tag at the end)
766-
# For existing repository - use as-is since already sorted when added to dictionary
778+
# For existing repository - use as-is since already processed
767779
$existingOrderedTags = @()
768780
if ($existingRepo.ApiCompatibleTags) {
769781
$existingOrderedTags += $existingRepo.ApiCompatibleTags
@@ -812,9 +824,9 @@ function Update-RepositoryDictionary {
812824
# Both Strict: Use intersection algorithm
813825
Write-Log "Both repositories are Strict mode, using intersection algorithm" -Level Debug
814826

815-
# Sort intersection if tag sorting is enabled
827+
# Sort intersection if tag sorting is enabled and we need to make chronological decisions
816828
if ($script:EnableTagSorting -and $tagDates.Count -gt 0) {
817-
$finalOrderedTags = Sort-TagsByDate -Tags $intersection -TagDates $tagDates -RepositoryUrl $repoUrl
829+
$finalOrderedTags = Sort-TagsByDate -Tags $intersection -TagDates $tagDates -RepositoryUrl $repoUrl -Context "intersection"
818830
Write-Log "Intersection after temporal sorting: $($finalOrderedTags -join ', ')" -Level Debug
819831
} else {
820832
$finalOrderedTags = $intersection
@@ -974,7 +986,6 @@ function Update-RepositoryDictionary {
974986

975987
# When switching to Strict mode, use the new repository's settings
976988
if ($script:EnableTagSorting -and $tagDates.Count -gt 0) {
977-
$sortedNewTags = Sort-TagsByDate -Tags $newOrderedTags -TagDates $tagDates -RepositoryUrl $repoUrl
978989
# In this case, the new tag is the definitive choice since we're adopting Strict mode
979990
$newTag = $newRepositoryTag
980991
$newApiCompatibleTags = $apiCompatibleTags
@@ -1015,23 +1026,18 @@ function Update-RepositoryDictionary {
10151026
return $true # Repository already checked out with correct tag
10161027
}
10171028
} else {
1018-
# New repository, add to dictionary with sorted API Compatible Tags if tag sorting enabled
1019-
$sortedApiCompatibleTags = $apiCompatibleTags
1020-
if ($script:EnableTagSorting -and $Recursive) {
1021-
# We'll sort the API Compatible Tags when we get the tag dates after checkout
1022-
# For now, store them as-is
1023-
$sortedApiCompatibleTags = $apiCompatibleTags
1024-
}
1029+
# New repository, add to dictionary
1030+
# Note: We don't sort API Compatible Tags here anymore - only during conflict resolution if needed
10251031

10261032
$script:RepositoryDictionary[$repoUrl] = @{
10271033
AbsolutePath = $absoluteBasePath
10281034
Tag = $newRepositoryTag
1029-
ApiCompatibleTags = $sortedApiCompatibleTags
1035+
ApiCompatibleTags = $apiCompatibleTags # Store as-is from JSON
10301036
ApiCompatibility = $apiCompatibility
10311037
AlreadyCheckedOut = $false
10321038
NeedCheckout = $false
10331039
CheckoutFailed = $false
1034-
TagDates = @{} # Will be populated after checkout
1040+
TagDates = @{} # Will be populated after checkout if EnableTagSorting is enabled
10351041
}
10361042

10371043
Write-Log "Added new repository to dictionary: '$repoUrl' with API Compatibility: $apiCompatibility" -Level Debug
@@ -1301,23 +1307,15 @@ function Invoke-GitCheckout {
13011307
}
13021308
}
13031309

1304-
# Fetch tag dates if tag sorting is enabled and this is the first checkout
1310+
# Fetch tag dates only if tag sorting is enabled and this is recursive mode
1311+
# This optimization only fetches tag dates when they might be needed for conflict resolution
13051312
if ($script:EnableTagSorting -and $Recursive) {
13061313
Write-Log "Tag sorting enabled, fetching tag dates for repository: $repoUrl" -Level Info
13071314
$tagDates = Get-GitTagDates -RepoPath $absoluteBasePath
13081315

1309-
# Store tag dates in repository dictionary and sort API Compatible Tags
1316+
# Store tag dates in repository dictionary
13101317
if ($script:RepositoryDictionary.ContainsKey($repoUrl)) {
13111318
$script:RepositoryDictionary[$repoUrl].TagDates = $tagDates
1312-
1313-
# Sort the API Compatible Tags now that we have tag dates
1314-
$currentApiTags = $script:RepositoryDictionary[$repoUrl].ApiCompatibleTags
1315-
if ($currentApiTags -and $tagDates.Count -gt 0) {
1316-
$sortedApiTags = Sort-TagsByDate -Tags $currentApiTags -TagDates $tagDates -RepositoryUrl $repoUrl
1317-
$script:RepositoryDictionary[$repoUrl].ApiCompatibleTags = $sortedApiTags
1318-
Write-Log "Sorted API Compatible Tags for repository '$repoUrl': $($sortedApiTags -join ', ')" -Level Debug
1319-
}
1320-
13211319
Write-Log "Stored tag dates for $($tagDates.Count) tags in repository dictionary" -Level Debug
13221320
}
13231321
}
@@ -1531,6 +1529,13 @@ function Process-DependencyFile {
15311529
if ($Recursive) {
15321530
$repoUrl = $repo.'Repository URL'
15331531
$wasNewCheckout = -not $script:RepositoryDictionary.ContainsKey($repoUrl)
1532+
1533+
# Log repository processing status
1534+
if (-not $wasNewCheckout) {
1535+
Write-Log "Processing repository: $repoUrl (already in dictionary)" -Level Info
1536+
} else {
1537+
Write-Log "Processing repository: $repoUrl (new repository)" -Level Info
1538+
}
15341539
}
15351540

15361541
if (Invoke-GitCheckout -Repository $repo -DependencyFilePath $DependencyFilePath) {
@@ -1715,13 +1720,19 @@ try {
17151720
Write-Log "Default API Compatibility: $($script:DefaultApiCompatibility)" -Level Info
17161721

17171722
if ($script:EnableTagSorting) {
1718-
Write-Log "Tag temporal sorting: ENABLED" -Level Info
1719-
Write-Log "Manual temporal ordering requirements relaxed in Permissive mode" -Level Info
1723+
Write-Log "Tag temporal sorting: ENABLED (default)" -Level Info
1724+
Write-Log "Tag sorting optimized to run only during API compatibility resolution" -Level Info
17201725
} else {
17211726
Write-Log "Tag temporal sorting: DISABLED" -Level Info
17221727
Write-Log "Manual temporal ordering required for API Compatible Tags" -Level Info
17231728
}
17241729

1730+
if ($Recursive) {
1731+
Write-Log "Recursive mode: ENABLED (default) with max depth: $MaxDepth" -Level Info
1732+
} else {
1733+
Write-Log "Recursive mode: DISABLED" -Level Info
1734+
}
1735+
17251736
# Calculate and log script hash in debug mode
17261737
if ($EnableDebug) {
17271738
$scriptContent = Get-Content -Path $MyInvocation.MyCommand.Path -Raw
@@ -1741,9 +1752,8 @@ try {
17411752
Write-Log "Debug logging enabled" -Level Info
17421753
}
17431754

1744-
if ($Recursive) {
1745-
Write-Log "Recursive mode enabled with max depth: $MaxDepth" -Level Info
1746-
}
1755+
# Note: Recursive mode is now enabled by default, but still log it
1756+
# (removed the separate recursive mode logging since it's now handled above)
17471757

17481758
# Check Git installation
17491759
if (-not (Test-GitInstalled)) {
@@ -1781,7 +1791,7 @@ try {
17811791

17821792
# If recursive mode is enabled, process nested dependencies
17831793
if ($Recursive -and $checkedOutRepos.Count -gt 0) {
1784-
Process-RecursiveDependencies -CheckedOutRepos $checkedOutRepos -DependencyFileName $DependencyFileName -CurrentDepth 1
1794+
Process-RecursiveDependencies -CheckedOutRepos $checkedOutRepos -DependencyFileName $dependencyFileName -CurrentDepth 1
17851795
}
17861796

17871797
# Show summary

0 commit comments

Comments
 (0)