#!/usr/bin/env pwsh # Git Sync Script with Gantt Integration # Runs daily at 10:30 AM param( [string]$RepoPath = "D:/fork_project/obsidian-notes" ) $InBoxPath = Join-Path $RepoPath "InBox" $GanttTag = "obsidian" $GitArgs = @("-c", "safe.directory=$RepoPath") function Resolve-GanttApp { $candidates = @( "C:/Users/Administrator/Desktop/我的/app_gant2/src-tauri/target/release/gantt-app.exe", "C:/Users/Administrator/Desktop/我的/app_gant2/src-tauri/target/debug/gantt-app.exe" ) foreach ($candidate in $candidates) { if (Test-Path $candidate) { return $candidate } } $searchRoot = "C:/Users/Administrator/Desktop" if (Test-Path $searchRoot) { $found = Get-ChildItem -Path $searchRoot -Filter "gantt-app.exe" -Recurse -ErrorAction SilentlyContinue | Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty FullName if ($found) { return $found } } return $null } $GanttApp = Resolve-GanttApp # Change to repo directory Set-Location $RepoPath function Invoke-GitCommand { param( [Parameter(Mandatory)] [string[]]$Arguments ) $output = & git @GitArgs @Arguments 2>&1 return [PSCustomObject]@{ Output = @($output) ExitCode = $LASTEXITCODE } } function Get-InBoxFileNames { if (Test-Path $InBoxPath) { return Get-ChildItem -Path $InBoxPath -File | Select-Object -ExpandProperty Name } return @() } # Function to get all Gantt tasks function Get-GanttTasks { if ($GanttApp -and (Test-Path $GanttApp)) { try { $result = & $GanttApp --cli list-tasks 2>$null | ConvertFrom-Json if ($result.ok -and $result.data.tasks) { return $result.data.tasks } } catch { Write-Host "Failed to get Gantt tasks: $_" } } return @() } # Function to show Windows notification function Show-Notification { param([string]$Title, [string]$Message) Add-Type -AssemblyName System.Windows.Forms $global:balloon = New-Object System.Windows.Forms.NotifyIcon $path = (Get-Process -Id $pid).Path $balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path) $balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning $balloon.BalloonTipText = $Message $balloon.BalloonTipTitle = $Title $balloon.Visible = $true $balloon.ShowBalloonTip(5000) } function Fail-AndExit { param( [string]$Title, [string]$Message ) Write-Host $Message Show-Notification -Title $Title -Message $Message exit 1 } function Test-RepoReady { if (-not (Test-Path $RepoPath)) { Fail-AndExit -Title "Git Sync Error" -Message "Repository path not found: $RepoPath" } $statusResult = Invoke-GitCommand -Arguments @("status", "--short", "--branch") if ($statusResult.ExitCode -ne 0) { $message = ($statusResult.Output -join [Environment]::NewLine).Trim() if ([string]::IsNullOrWhiteSpace($message)) { $message = "Failed to read git status." } Fail-AndExit -Title "Git Sync Error" -Message $message } $dirtyEntries = $statusResult.Output | Where-Object { $_ -and $_ -notmatch "^## " } if ($dirtyEntries.Count -gt 0) { $preview = ($dirtyEntries | Select-Object -First 5) -join "; " $message = "Working tree is not clean. Resolve or commit local changes before auto sync. $preview" Fail-AndExit -Title "Git Sync Blocked" -Message $message } } function Add-GanttTask { param([string]$TaskName) $today = Get-Date -Format "yyyy-MM-dd" $taskId = [Guid]::NewGuid().ToString() if ($GanttApp -and (Test-Path $GanttApp)) { try { & $GanttApp --cli add-task --id $taskId --name $TaskName --start $today --description "Auto-created from InBox sync" --tag $GanttTag 2>$null Write-Host "Created Gantt task: $TaskName" } catch { Write-Host "Failed to create Gantt task: $_" } } else { Write-Host "Gantt app not found" } } function Update-GanttTaskTag { param( [string]$TaskId, [string]$TaskName ) if ($GanttApp -and (Test-Path $GanttApp)) { try { & $GanttApp --cli update-task --id $TaskId --tag $GanttTag 2>$null Write-Host "Updated Gantt task tag: $TaskName" } catch { Write-Host "Failed to update Gantt task tag: $_" } } } function Remove-GanttTask { param([string]$TaskId) if ($GanttApp -and (Test-Path $GanttApp)) { try { & $GanttApp --cli delete-task --id $TaskId 2>$null Write-Host "Deleted Gantt task: $TaskId" } catch { Write-Host "Failed to delete Gantt task: $_" } } } function Sync-InBoxTasks { if (-not ($GanttApp -and (Test-Path $GanttApp))) { Write-Host "Skipping Gantt sync because gantt-app.exe was not found" return } $inboxFiles = Get-InBoxFileNames $ganttTasks = Get-GanttTasks $existingInboxTasks = $ganttTasks | Where-Object { $_.name -match "^Process InBox: " } foreach ($task in $existingInboxTasks) { $taskFileName = $task.name -replace "^Process InBox: ", "" if ($taskFileName -notin $inboxFiles) { Write-Host "File no longer exists, deleting task: $($task.name)" Remove-GanttTask -TaskId $task.id } } foreach ($file in $inboxFiles) { $taskName = "Process InBox: $file" $matchingTasks = @($existingInboxTasks | Where-Object { $_.name -eq $taskName }) if ($matchingTasks.Count -eq 0) { Add-GanttTask -TaskName $taskName continue } foreach ($task in $matchingTasks) { if ($task.tag -ne $GanttTag) { Update-GanttTaskTag -TaskId $task.id -TaskName $task.name } else { Write-Host "Task already exists for: $file" } } } } # Perform git pull Test-RepoReady Write-Host "Starting git pull at $(Get-Date)..." $pullResult = Invoke-GitCommand -Arguments @("pull") $pullOutput = $pullResult.Output $pullExitCode = $pullResult.ExitCode if ($pullExitCode -ne 0) { $message = "Git pull failed: " + (($pullOutput -join [Environment]::NewLine).Trim()) Fail-AndExit -Title "Git Sync Error" -Message $message } Write-Host "Git pull completed: $($pullOutput -join [Environment]::NewLine)" # Check for merge conflicts if ($pullOutput -match "CONFLICT|conflict|Automatic merge failed") { Show-Notification -Title "Git Sync Conflict" -Message "Merge conflicts detected during git pull. Please resolve manually." exit 1 } # Sync Gantt tasks against the full current InBox state Start-Sleep -Seconds 2 Sync-InBoxTasks # Perform git push Write-Host "Starting git push..." $pushResult = Invoke-GitCommand -Arguments @("push") $pushOutput = $pushResult.Output $pushExitCode = $pushResult.ExitCode if ($pushExitCode -ne 0) { $pushText = ($pushOutput -join [Environment]::NewLine).Trim() if ($pushText -match "rejected|failed|conflict|non-fast-forward") { Show-Notification -Title "Git Push Conflict" -Message "Push rejected. Please pull and resolve conflicts manually." } else { Show-Notification -Title "Git Push Error" -Message "Git push failed: $pushText" } exit 1 } Write-Host "Git push completed successfully at $(Get-Date)"