static void Main(string[] args) { int exitCode = 0; IRepositoryProxy sourceRep = null; IRepositoryProxy destRep = null; do { DateTime startTime = DateTime.Now; ManifestConsole console = new ManifestConsole(); int argIndex = 0; string commandArg = "help"; if (argIndex < args.Count()) { commandArg = args[argIndex++]; } bool seedCommand = false; bool validateCommand = false; switch (commandArg) { case "help": case "diff": case "update": case "sync": case "mirror": break; case "seed": seedCommand = true; break; case "validateCrypt": validateCommand = true; break; default: console.WriteLine("Unrecognized command \"" + commandArg + "\""); Environment.Exit(1); break; } if (commandArg == "help") { console.Write(Properties.Resources.RepositorySyncHelp); Environment.Exit(1); break; } bool parseTwoRepositoryStrings = args.Length >= 3; string sourceRepString = ""; string destRepString = ""; if (validateCommand && args.Length >= 2) { // Special case only has source repository sourceRepString = args[argIndex++]; } else if (parseTwoRepositoryStrings == true) { // Skip repositories for now and process options sourceRepString = args[argIndex++]; destRepString = args[argIndex++]; } else { console.WriteLine("Source or destination repositories were not supplied."); exitCode = 1; break; } // Process options bool time = false; bool retry = false; String sourceKeyString = null; String destKeyString = null; while (argIndex < args.Length) { string nextArg = args[argIndex++]; switch (nextArg) { case "-silent": console.Silent = true; break; case "-detail": console.Detail = true; break; case "-noTimeout": RemoteRepositoryProxy.RequestReadWriteTimeout = System.Threading.Timeout.Infinite; RemoteRepositoryProxy.RequestTimeout = System.Threading.Timeout.Infinite; break; case "-time": time = true; break; case "-sourceKey": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { sourceKeyString = args[argIndex++]; } break; case "-destKey": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { destKeyString = args[argIndex++]; } break; case "-cryptSource": console.Write("Enter source key: "); sourceKeyString = console.EnterPassword(); break; case "-cryptDest": console.Write("Enter dest key: "); destKeyString = console.EnterPassword(); break; case "-retry": retry = true; break; default: console.WriteLine("Unrecognized parameter \" " + nextArg + "\""); Environment.Exit(1); break; } } // Resolve repositories bool sourceReadOnly = true; bool destReadOnly = false; if (commandArg == "diff") { destReadOnly = true; } else if (commandArg == "sync") { sourceReadOnly = false; } bool remoteSource = RemoteRepositoryProxy.IsRemoteRepositoryString( sourceRepString); bool remoteDest = RemoteRepositoryProxy.IsRemoteRepositoryString( destRepString); if (remoteSource == false) { try { sourceRep = new LocalRepositoryProxy( new System.IO.DirectoryInfo(sourceRepString), sourceReadOnly); if (sourceKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( sourceRep, sourceKeyString, sourceReadOnly); ReportCrypt(cryptProxy, "Source", console); sourceRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteDest == false && seedCommand == false && destRepString != "") { try { destRep = new LocalRepositoryProxy( new System.IO.DirectoryInfo(destRepString), destReadOnly); if (destKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( destRep, destKeyString, destReadOnly); ReportCrypt(cryptProxy, "Dest", console); destRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteSource == true) { try { sourceRep = new RemoteRepositoryProxy( sourceRepString, destRep.Manifest); if (sourceKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( sourceRep, sourceKeyString, sourceReadOnly); ReportCrypt(cryptProxy, "Source", console); sourceRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteDest == true && seedCommand == false && destRepString != "") { try { destRep = new RemoteRepositoryProxy( destRepString, sourceRep.Manifest); if (destKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( destRep, destKeyString, destReadOnly); ReportCrypt(cryptProxy, "Dest", console); destRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (sourceRep == null && destRep == null) { console.WriteLine("Could not resolve a source or destination repository."); exitCode = 1; break; } else if (sourceRep == null) { console.WriteLine("Could not resolve a source repository."); exitCode = 1; break; } else if (destRep == null && seedCommand == false && validateCommand == false) { console.WriteLine("Could not resolve a destination repository."); exitCode = 1; break; } switch (commandArg) { case "update": case "sync": case "mirror": if (sourceRep != null && destRep != null && sourceRep.Manifest.Guid.Equals( destRep.Manifest.Guid) == false) { console.WriteLine("Source and destination GUIDs are different."); exitCode = 1; } break; } if (exitCode == 1) { break; } RepositorySync syncTool = null; if (seedCommand == false && validateCommand == false) { syncTool = new RepositorySync(sourceRep, destRep); syncTool.Retry = retry; syncTool.WriteLogDelegate = delegate(String message) { console.Write(message); }; syncTool.CompareManifests(); } // Process command if (time) { console.WriteLine("Started: " + startTime.ToString()); } switch (commandArg) { case "diff": ShowDiff(syncTool, console); break; case "update": syncTool.DoUpdate(); break; case "sync": syncTool.BothWays = true; syncTool.DoUpdate(); break; case "mirror": syncTool.Mirror = true; syncTool.DoUpdate(); break; case "seed": if (destKeyString == null) { LocalRepositoryProxy.SeedLocalRepository( sourceRep.Manifest, destRepString, console); } else { CryptRepositoryProxy.SeedLocalRepository( sourceRep.Manifest, destKeyString, destRepString, console); } break; case "validateCrypt": CryptRepositoryProxy sourceCryptRep = sourceRep as CryptRepositoryProxy; if (sourceCryptRep == null) { console.WriteLine("The validateCrypt command requires an encrypted repository."); exitCode = 1; break; } long fileCount = sourceCryptRep.Validate(console); console.WriteLine(fileCount + " files checked."); break; } if (time) { DateTime finishedTime = DateTime.Now; console.WriteLine("Finished: " + finishedTime.ToString()); console.WriteLine("Duration: " + (finishedTime - startTime).ToString()); } } while (false); if (sourceRep != null) { sourceRep.CleanupBeforeExit(); sourceRep = null; } if (destRep != null) { destRep.CleanupBeforeExit(); destRep = null; } Environment.Exit(exitCode); }
static void Main(string[] args) { // Initialize some things ManifestConsole console = new ManifestConsole(); RepositoryTool tool = new RepositoryTool(); tool.WriteLogDelegate = delegate(String message) { console.Write(message); }; DateTime startTime = DateTime.Now; int exitCode = 0; int argIndex = 0; // Give the user some help if they need it string commandArg = "help"; if (args.Length > 0) { commandArg = args[argIndex++]; } // Initial screen for valid command switch (commandArg) { case "create": case "validate": case "status": case "update": case "edit": case "groom": case "clear": case "info": case "help": break; default: console.WriteLine("Unrecognized command \"" + commandArg + "\""); exitCode = 1; Environment.Exit(exitCode); break; } // Set up options and parameters bool ignoreDate = false; bool ignoreNew = false; bool time = false; bool all = false; bool force = false; bool ignoreDefault = false; bool recursive = false; bool cascade = false; bool manifestInfoChanged = false; bool noTouch = false; bool confirmUpdate = false; bool forceJSON = false; bool forceBinary = false; string repositoryName = null; string repositoryDescription = null; string hashMethod = null; string manifestFilePathNotRecursive = null; List <String> ignoreList = new List <string>(); List <String> dontIgnoreList = new List <string>(); // Parse options and parameters while (argIndex < args.Length) { string nextArg = args[argIndex++]; switch (nextArg) { case "-all": all = true; break; case "-silent": console.Silent = true; tool.WriteLogDelegate = null; break; case "-detail": console.Detail = true; break; case "-showProgress": tool.ShowProgress = true; break; case "-ignoreDate": ignoreDate = true; break; case "-ignoreNew": ignoreNew = true; break; case "-reHash": tool.AlwaysCheckHash = true; break; case "-newHash": tool.MakeNewHash = true; break; case "-time": time = true; break; case "-name": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { repositoryName = args[argIndex++]; } break; case "-description": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { repositoryDescription = args[argIndex++]; } break; case "-hashMethod": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { hashMethod = args[argIndex++]; } break; case "-backDate": tool.BackDate = true; break; case "-trackMoves": tool.TrackMoves = true; break; case "-trackDuplicates": tool.TrackDuplicates = true; break; case "-ignore": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { ignoreList.Add(args[argIndex++]); } break; case "-dontIgnore": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { dontIgnoreList.Add(args[argIndex++]); } break; case "-manifestFile": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { manifestFilePathNotRecursive = args[argIndex++]; } break; case "-force": force = true; break; case "-ignoreDefault": ignoreDefault = true; break; case "-recursive": recursive = true; break; case "-cascade": cascade = true; break; case "-noTouch": noTouch = true; break; case "-confirmUpdate": confirmUpdate = true; break; case "-forceJSON": forceJSON = true; break; case "-forceBinary": forceBinary = true; break; default: console.WriteLine("Unrecognized parameter \" " + nextArg + "\""); commandArg = ""; exitCode = 1; break; } } if (time) { console.WriteLine("Started: " + startTime.ToString()); } // Prepare a list of paths to be processed List <String> manifestFilePaths = new List <string>(); if (recursive) { FindManifests( new DirectoryInfo(Directory.GetCurrentDirectory()), cascade, manifestFilePaths); } else { if (manifestFilePathNotRecursive == null) { // Default manifest file name located in current directory. manifestFilePathNotRecursive = PathUtilities.NativeFromNativeAndStandard( System.IO.Directory.GetCurrentDirectory(), Manifest.DefaultManifestStandardFilePath); } manifestFilePaths.Add(manifestFilePathNotRecursive); } // Outer loop over manifests foreach (String manifestFilePath in manifestFilePaths) { if (recursive == true) { console.WriteLine(Path.GetDirectoryName(manifestFilePath) + ":"); } // Initialize the tool for this manifest tool.Clear(); tool.Manifest = null; // Second copy of the manifest which will remain unmodified // and possibly rewritten after a validate. Manifest manifestForValidateDateUpdate = null; FileInfo fileInfo = new FileInfo(manifestFilePath); if (recursive == true) { tool.RootDirectory = fileInfo.Directory; } else { // In case -manifestFile was specified, we always want this: tool.RootDirectory = new DirectoryInfo( System.IO.Directory.GetCurrentDirectory()); } // Command-specific code to initialize tool object and // manifest object, and then execute command using tool. switch (commandArg) { case "create": { bool doCreate = true; if (force == false) { if (File.Exists(manifestFilePath)) { doCreate = false; console.Write("Replace existing manifest file? "); doCreate = console.CheckConfirm(); } } if (doCreate == true) { tool.Manifest = tool.MakeManifest(); tool.Manifest.UseJSON = true; } break; } case "validate": case "status": case "update": case "edit": case "groom": { if (commandArg == "validate") { tool.AlwaysCheckHash = true; } else if (commandArg == "update") { tool.Update = true; } bool different = false; try { tool.Manifest = Manifest.ReadManifestFile(manifestFilePath); if (commandArg == "validate" && noTouch == false) { // Read a second copy which will remain unmodified manifestForValidateDateUpdate = Manifest.ReadManifestFile(manifestFilePath); } } catch (Exception ex) { console.ReportException(ex); console.WriteLine("Could not read manifest."); Environment.Exit(1); } if (tool.Manifest == null) { exitCode = 1; } else if (commandArg != "edit") { tool.DoUpdate(); if (tool.MissingFiles.Count > 0) { console.WriteLine(tool.MissingFiles.Count.ToString() + " files are missing."); console.DetailFiles(tool.MissingFiles); different = true; } if (tool.ChangedFiles.Count > 0) { console.WriteLine(tool.ChangedFiles.Count.ToString() + " files have changed content."); console.DetailFiles(tool.ChangedFiles); different = true; } if (tool.NewFiles.Count > 0) { console.WriteLine(tool.NewFiles.Count.ToString() + " files are new."); console.DetailFiles(tool.NewFiles); if (ignoreNew == false) { different = true; } } if (tool.LastModifiedDateFiles.Count > 0) { console.WriteLine(tool.LastModifiedDateFiles.Count.ToString() + " files have last-modified dates which are different."); console.DetailFiles(tool.LastModifiedDateFiles); if (ignoreDate == false) { different = true; } } if (tool.ErrorFiles.Count > 0) { console.WriteLine(tool.ErrorFiles.Count.ToString() + " files have errors."); console.DetailFiles(tool.ErrorFiles); different = true; } if (tool.MovedFiles.Count > 0) { console.WriteLine(tool.MovedFiles.Count.ToString() + " files were moved."); console.DetailFiles(tool.MovedFileOrder, tool.MovedFiles); different = true; } if (tool.DuplicateFiles.Keys.Count > 0) { console.WriteLine(tool.DuplicateFiles.Keys.Count.ToString() + " file hashes were duplicates."); console.DetailFiles(tool.DuplicateFiles); } if (tool.NewlyIgnoredFiles.Count > 0) { console.WriteLine(tool.NewlyIgnoredFiles.Count.ToString() + " files are newly ignored."); console.DetailFiles(tool.NewlyIgnoredFiles); } if (tool.IgnoredFiles.Count > 1) { console.WriteLine(tool.IgnoredFiles.Count.ToString() + " files were ignored."); if (all == true) { console.DetailFiles(tool.IgnoredFiles); } } console.WriteLine(tool.FileCheckedCount.ToString() + " files were checked."); if (commandArg == "validate") { if (different) { console.WriteLine("Problems found."); exitCode = 1; } else { console.WriteLine("No problems."); } } } break; } case "clear": try { tool.Manifest = Manifest.ReadManifestFile(manifestFilePath); } catch (Exception ex) { console.ReportException(ex); console.WriteLine("Could not read manifest."); } if (tool.Manifest != null) { bool doClear = true; if (force == false) { console.Write("Clear " + tool.Manifest.CountFiles().ToString() + " files from the manifest? "); doClear = console.CheckConfirm(); } if (doClear == true) { if (tool.Manifest == null) { exitCode = 1; } else { tool.Manifest.RootDirectory.Files.Clear(); tool.Manifest.RootDirectory.Subdirectories.Clear(); } } } break; case "info": try { tool.Manifest = Manifest.ReadManifestFile(manifestFilePath); } catch (Exception ex) { console.ReportException(ex); console.WriteLine("Could not read manifest."); } if (tool.Manifest == null) { exitCode = 1; } else { if (tool.Manifest.Name != null) { console.WriteLine("Name: " + tool.Manifest.Name); } console.WriteLine("GUID: " + tool.Manifest.Guid.ToString()); if (tool.Manifest.DefaultHashMethod != null) { console.WriteLine("Default hash method: " + tool.Manifest.DefaultHashMethod); } console.WriteLine("Date of creation: " + (tool.Manifest.InceptionDateUtc.ToLocalTime()).ToString()); console.WriteLine("Date of last update: " + (tool.Manifest.LastUpdateDateUtc.ToLocalTime()).ToString()); console.WriteLine("Last change of manifest info: " + (tool.Manifest.ManifestInfoLastModifiedUtc.ToLocalTime()).ToString()); console.WriteLine("Date of last validation: " + (tool.Manifest.LastValidateDateUtc.ToLocalTime()).ToString()); NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat; nfi.NumberDecimalDigits = 0; console.WriteLine("Total number of files: " + tool.Manifest.CountFiles().ToString("N", nfi)); console.WriteLine("Total number of bytes: " + tool.Manifest.CountBytes().ToString("N", nfi)); if (tool.Manifest.IgnoreList.Count > 0) { console.WriteLine("Ignoring these file patterns:"); foreach (String nextIgnore in tool.Manifest.IgnoreList) { console.WriteLine(" " + nextIgnore); } } } if (tool.Manifest.Description != null) { console.WriteLine(); console.WriteLine("Description: "); console.WriteLine(tool.Manifest.Description); } break; case "help": console.Write(Properties.Resources.RepositoryToolHelp); break; case "": break; } if (tool.Manifest != null) { if (forceJSON) { tool.Manifest.UseJSON = true; } if (forceBinary) { tool.Manifest.UseJSON = false; } } // Command-specific code to write the manifest, and possibly // delete some files if grooming. switch (commandArg) { case "create": case "update": case "edit": case "clear": if (tool.Manifest != null) { if (repositoryName != null) { tool.Manifest.Name = repositoryName; manifestInfoChanged = true; } if (repositoryDescription != null) { tool.Manifest.Description = repositoryDescription; manifestInfoChanged = true; } if (hashMethod != null) { tool.Manifest.DefaultHashMethod = hashMethod; manifestInfoChanged = true; } if (ignoreList.Count > 0) { foreach (String nextIgnore in ignoreList) { if (tool.Manifest.IgnoreList.Contains(nextIgnore) == false) { tool.Manifest.IgnoreList.Add(nextIgnore); } } manifestInfoChanged = true; } if (dontIgnoreList.Count > 0) { foreach (String nextIgnore in dontIgnoreList) { if (tool.Manifest.IgnoreList.Contains(nextIgnore) == true) { tool.Manifest.IgnoreList.Remove(nextIgnore); } } manifestInfoChanged = true; } if (ignoreDefault == true) { tool.Manifest.IgnoreList.Clear(); Manifest defaultPrototype = tool.MakeManifest(); foreach (String nextIgnore in defaultPrototype.IgnoreList) { tool.Manifest.IgnoreList.Add(nextIgnore); } manifestInfoChanged = true; } if (manifestInfoChanged) { tool.Manifest.ManifestInfoLastModifiedUtc = DateTime.UtcNow; } if (confirmUpdate) { console.Write("Update manifest? "); bool writeManifest = console.CheckConfirm(); if (writeManifest == false) { break; } } try { tool.Manifest.WriteManifestFile(manifestFilePath); } catch (Exception ex) { console.ReportException(ex); console.WriteLine("Could not write manifest."); exitCode = 1; } } break; case "validate": if (noTouch == false) { manifestForValidateDateUpdate.LastValidateDateUtc = DateTime.UtcNow; try { manifestForValidateDateUpdate.WriteManifestFile( manifestFilePath); } catch (Exception ex) { console.ReportException(ex); console.WriteLine("Could not write manifest."); exitCode = 1; } } break; case "groom": if (tool.NewFilesForGroom.Count > 0) { bool doGroom = true; if (force == false) { console.Write("Delete " + tool.NewFilesForGroom.Count.ToString() + " new files? "); doGroom = console.CheckConfirm(); } if (doGroom == true) { foreach (FileInfo delFile in tool.NewFilesForGroom) { delFile.Delete(); } } } if (all == true && tool.IgnoredFilesForGroom.Count > 0) { bool doGroomAll = true; if (force == false) { console.Write("Delete " + tool.IgnoredFilesForGroom.Count.ToString() + " ignored files? "); doGroomAll = console.CheckConfirm(); } if (doGroomAll == true) { foreach (FileInfo delFile in tool.IgnoredFilesForGroom) { delFile.Delete(); } } } break; } if (recursive) { console.WriteLine(); } } if (time) { DateTime finishedTime = DateTime.Now; console.WriteLine("Finished: " + finishedTime.ToString()); console.WriteLine("Duration: " + (finishedTime - startTime).ToString()); } Environment.Exit(exitCode); }