Editor/SyncToolWindow.PullSupport.cs
#nullable disable
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
public partial class SyncToolWindow
{
private void PullAllChangedResources()
{
if ( _busy || !SyncToolConfig.IsValid ) return;
var ids = GetPullableResourceIds();
if ( ids.Length == 0 )
{
_status = "No resources are ready to pull. Run Check for Updates first.";
Update();
return;
}
ConfirmDialog.Show(
"Pull All",
$"This will pull {ids.Length} resource(s) from the selected target ({(_publishTarget == "next" ? "Staged/Main" : "Live")}). Each local file gets a .bak backup before overwrite.",
() => _ = PullAllChangedResourcesAsync( ids ),
detail: string.Join( "\n", ids.Select( DescribeSyncItem ) ) );
}
private async System.Threading.Tasks.Task PullAllChangedResourcesAsync( string[] ids )
{
foreach ( var id in ids )
{
await DoPullItem( id );
}
_status = $"Pulled {ids.Length} resource(s)";
Update();
}
private string[] GetPullableResourceIds()
{
return _items
.Where( kv => kv.Value.RemoteDiffers || kv.Value.Status == SyncStatus.RemoteOnly || kv.Value.Status == SyncStatus.Differs || kv.Value.Status == SyncStatus.MergeAvailable )
.Select( kv => kv.Key )
.Where( id => id.StartsWith( "ep_" ) || id.StartsWith( "col_" ) || id.StartsWith( "wf_" ) )
.OrderBy( id => id, StringComparer.OrdinalIgnoreCase )
.ToArray();
}
private bool IsLocalChangedSinceCached( string id, ItemState cached )
{
if ( string.IsNullOrWhiteSpace( cached.LocalYaml ) ) return false;
try
{
if ( id.StartsWith( "ep_" ) )
{
var file = _endpointFiles.FirstOrDefault( f => ResourceIdFromFile( f, "endpoint" ) == id[3..] );
return CurrentYamlDiffers( file, "endpoint", cached.LocalYaml );
}
if ( id.StartsWith( "col_" ) )
{
var file = _collectionFiles.FirstOrDefault( f => ResourceIdFromFile( f, "collection" ) == id[4..] );
return CurrentYamlDiffers( file, "collection", cached.LocalYaml );
}
if ( id.StartsWith( "wf_" ) )
{
var file = _workflowFiles.FirstOrDefault( f => ResourceIdFromFile( f, "workflow" ) == id[3..] );
return CurrentYamlDiffers( file, "workflow", cached.LocalYaml );
}
}
catch { }
return false;
}
private bool CurrentYamlDiffers( string file, string kind, string cachedYaml )
{
if ( string.IsNullOrWhiteSpace( file ) || !File.Exists( file ) ) return false;
if ( !TryReadLocalResourceFile( file, kind, out var resource ) ) return false;
var current = SyncToolYamlRenderer.RenderFromJson( JsonSerializer.Serialize( resource, new JsonSerializerOptions { WriteIndented = true } ) );
return !string.Equals( NormalizeLineEndings( current ).Trim(), NormalizeLineEndings( cachedYaml ).Trim(), StringComparison.Ordinal );
}
private static string NormalizeLineEndings( string text ) => (text ?? "").Replace( "\r\n", "\n" ).Replace( '\r', '\n' );
private void BackupLocalFileForPull( string id )
{
var file = GetLocalFileForItem( id );
if ( string.IsNullOrWhiteSpace( file ) || !File.Exists( file ) ) return;
var backup = $"{file}.bak.{DateTime.Now:yyyyMMddHHmmss}";
File.Copy( file, backup, overwrite: false );
}
private string GetLocalFileForItem( string id )
{
if ( id.StartsWith( "ep_" ) ) return _endpointFiles.FirstOrDefault( f => ResourceIdFromFile( f, "endpoint" ) == id[3..] );
if ( id.StartsWith( "col_" ) ) return _collectionFiles.FirstOrDefault( f => ResourceIdFromFile( f, "collection" ) == id[4..] );
if ( id.StartsWith( "wf_" ) ) return _workflowFiles.FirstOrDefault( f => ResourceIdFromFile( f, "workflow" ) == id[3..] );
return null;
}
}