Exemplo n.º 1
0
 /// <summary>
 /// Configure the OptionsSet object used to parse command line parameters
 /// </summary>
 /// <param name="parameters"></param>
 /// <returns></returns>
 private static OptionSet ConfigureOptions(ProgramParams parameters)
 {
     return(new OptionSet()
            .Add("a|analyse", "analysis only, no synchronisation", a => parameters.AnalyseOnly = true)
            .Add("af|analyse first", "analysis only first and only synch if within limits defined in -ld and -lf options",
                 af => parameters.AnalyseFirst = true)
            .Add("xh|exclude hidden", "exclude hidden files and directories", xh => parameters.ExcludeHidden = true)
            .Add("xi|exclude identical", "exclude identical files from the report", xi => parameters.ExcludeIdenticalFiles = true)
            .Add("df|delete files", "delete files in destination which do not appear in source", df => parameters.DeleteFilesFromDest = true)
            .Add("dd|delete dirs", "delete directories in destination which do not appear in source", dd => parameters.DeleteDirsFromDest = true)
            .Add("xf|exclude files=", "exclude files from source that match any of the filespecs",
                 xf => parameters.ExcludeFiles = FormRegexListfromString(xf, parameters.UseRegex))
            .Add("xd|exclude directories=", "exclude directories from source that match any of the filespecs",
                 xd => parameters.ExcludeDirs = FormRegexListfromString(xd, parameters.UseRegex))
            .Add("if|include files=", "only include files from source that match one of the filespecs",
                 inf => parameters.IncludeFiles = FormRegexListfromString(inf, parameters.UseRegex))
            .Add("id|include directories=", "include directories from source that match one of the filespecs",
                 ind => parameters.IncludeDirs = FormRegexListfromString(ind, parameters.UseRegex))
            .Add("ndf|exclude delete files=", "exclude files from deletion that match any of the filespecs",
                 ndf => parameters.DeleteExcludeFiles = FormRegexListfromString(ndf, parameters.UseRegex))
            .Add("ndd|exclude delete directories=", "Exclude directories from deletion that match any of the filespecs",
                 ndd => parameters.DeleteExcludeDirs = FormRegexListfromString(ndd, parameters.UseRegex))
            .Add("ld|limit directory synch=", "limit on the number of directories that will be synchronised if the --af option is set",
                 ( uint ld ) => parameters.DirectorySynchLimit = ld)
            .Add("lf|limit file synch=", "limit on the number of files that will be synchronised if the --af option is set",
                 ( uint lf ) => parameters.FileSynchLimit = lf));
 }
Exemplo n.º 2
0
        /// <summary>
        /// Deserialise an xml configuration file into a set of backup jobs
        /// </summary>
        /// <param name="backups"></param>
        /// <param name="configFile"></param>
        /// <returns></returns>
        private static bool GetOptionsFromXmlFile(List <ProgramParams> backups, string configFile)
        {
            bool success = true;

            try
            {
                // Deserialise the file contents into a Configuration object
                Configuration xmlConfig = (Configuration) new XmlSerializer(typeof(Configuration)).Deserialize(new FileStream(configFile, FileMode.Open));

                // Now copy fields from the Configuration object to the parameters, one InputParams per backup job
                foreach (Backup backup in xmlConfig.Backups)
                {
                    ProgramParams parameters = new ProgramParams();

                    // Common options
                    parameters.AnalyseOnly           = xmlConfig.Options.analyseOnly;
                    parameters.ExcludeHidden         = xmlConfig.Options.excludeHidden;
                    parameters.ExcludeIdenticalFiles = xmlConfig.Options.excludeIdentical;
                    parameters.DeleteDirsFromDest    = xmlConfig.Options.deleteDirectories;
                    parameters.DeleteFilesFromDest   = xmlConfig.Options.deleteFiles;
                    parameters.UseRegex = xmlConfig.Options.useRegex;

                    // Specific to this backup
                    parameters.Name                 = backup.name;
                    parameters.SourceDirectory      = new DirectoryInfo(backup.source).FullName;
                    parameters.DestinationDirectory = new DirectoryInfo(backup.destination).FullName;

                    if (backup.directoryExcludes.directoryFilter != null)
                    {
                        parameters.ExcludeDirs = RegexListFromStringList(backup.directoryExcludes.directoryFilter, parameters.UseRegex);
                    }

                    if (backup.directoryIncludes.directoryFilter != null)
                    {
                        parameters.IncludeDirs = RegexListFromStringList(backup.directoryIncludes.directoryFilter, parameters.UseRegex);
                    }

                    backups.Add(parameters);
                }
            }
            catch (FileNotFoundException nfException)
            {
                Console.Write("SynchApp: ");
                Console.WriteLine(nfException.Message);
                success = false;
            }
            catch (InvalidOperationException ioException)
            {
                Console.Write("SynchApp: ");
                Console.WriteLine(ioException.Message);
                if (ioException.InnerException != null)
                {
                    Console.WriteLine(ioException.InnerException.Message);
                }

                success = false;
            }

            return(success);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Validate option combinations
        /// </summary>
        /// <param name="options"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private static bool ValidateOptions(OptionSet options, ProgramParams parameters)
        {
            bool success = false;

            // Check that both includes and excludes have not been defined
            if (((parameters.IncludeFiles == null) || (parameters.ExcludeFiles == null)) &&
                ((parameters.IncludeDirs == null) || (parameters.ExcludeDirs == null)))
            {
                // Deletion exclusions should only be defined if destination deletion has been specified
                if (((parameters.DeleteFilesFromDest == true) || (parameters.DeleteExcludeFiles == null)) &&
                    ((parameters.DeleteDirsFromDest == true) || (parameters.DeleteExcludeDirs == null)))
                {
                    // If the Analyse First option has been set then one of the limits should also be specified
                    if ((parameters.AnalyseFirst == false) ||
                        ((parameters.AnalyseOnly == false) && ((parameters.DirectorySynchLimit + parameters.FileSynchLimit) > 0)))
                    {
                        success = true;
                    }
                    else
                    {
                        if (parameters.AnalyseOnly == true)
                        {
                            Console.WriteLine("Error: analyse first and analyse only options cannot both be set.");
                            DisplayHelp(options);
                        }
                        else
                        {
                            Console.WriteLine("Error: analyse first option requries a limit ( -ld or -lf ).");
                            DisplayHelp(options);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("Error: exclude-from-deletion options (-ndf and -ndd) require deletion (-df or -dd) enabled.");
                    DisplayHelp(options);
                }
            }
            else
            {
                Console.WriteLine("Error: cannot include and exclude items at the same time.");
                DisplayHelp(options);
            }

            return(success);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Main entry point for the SynchApp program
        /// Parse the command line arguements, perform some basic validation and start the synchronisation process
        /// </summary>
        /// <param name="args"></param>
        static int Main(string[] args)
        {
            ExitCode success        = ExitCode.Success;
            int      errorCode      = ( int )success;
            bool     commandLineJob = true;

            try
            {
                // Collection of InputParams one per backup job
                List <ProgramParams> backupJobs = new List <ProgramParams>();

                // Assume that the options for a single backup is specified on the command line and only a single InputParams object
                // is required
                ProgramParams commandParameters = new ProgramParams();
                OptionSet     options           = ConfigureOptions(commandParameters);

                // Parse the options and the left over directories
                List <string> directories = options.Parse(args);

                // If two unmatched strings have been specified then assume that the command line includes the source and destination
                // and that the InputParams will be set by the OptionSet
                if (directories.Count == 2)
                {
                    commandParameters.SourceDirectory      = new DirectoryInfo(directories[0]).FullName;
                    commandParameters.DestinationDirectory = new DirectoryInfo(directories[1]).FullName;

                    backupJobs.Add(commandParameters);
                }
                else if (directories.Count == 1)
                {
                    // Assume that if a single file has been specified then it is an xml configuration file
                    commandLineJob = false;

                    if (GetOptionsFromXmlFile(backupJobs, directories[0]) == false)
                    {
                        DisplayHelp(options);
                        success = ExitCode.XmlError;
                    }
                }
                else
                {
                    DisplayHelp(options);
                    success = ExitCode.DirectoryError;
                }

                if (success == ExitCode.Success)
                {
                    // If this is a command line job then perform it and return its success code
                    if (commandLineJob == true)
                    {
                        success = PerformBackup(backupJobs[0], options);

                        // Include destination file and directory deletions in the error code if successfull
                        if (success == ExitCode.Success)
                        {
                            errorCode += ( int )(((UnmatchedDestinationFile > 255 ? 255 : UnmatchedDestinationFile) & 255) << 8);
                            errorCode += ( int )(((UnmatchedDestinationDirectory > 255 ? 255 : UnmatchedDestinationDirectory) & 255) << 16);
                        }
                    }
                    else
                    {
                        // Set up alternative console logging
                        Console.SetOut(new Logging(30));

                        // Process each backup job until
                        foreach (ProgramParams job in backupJobs)
                        {
                            PerformBackup(job, options);
                        }
                    }
                }
            }
            catch (OptionException oException)
            {
                Console.Write("SynchApp: ");
                Console.WriteLine(oException.Message);
                Console.WriteLine("Try 'SynchApp --help' for more information");
                success = ExitCode.DirectoryError;
            }
            catch (NotSupportedException nsException)
            {
                Console.Write("SynchApp: ");
                Console.WriteLine(nsException.Message);
                Console.WriteLine("Try 'SynchApp --help' for more information");
                success = ExitCode.DirectoryError;
            }

            // Include the success code in the erorr code
            errorCode += ( int )success;

            return(errorCode);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Carry out a backup job as defined by options in the ProgramParams
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        private static ExitCode PerformBackup(ProgramParams parameters, OptionSet options)
        {
            ExitCode success = ExitCode.Success;

            ResetLocalCounts();

            // Check that at least the source directory exists and that the directories don't overlap in some way
            if (Directory.Exists(parameters.SourceDirectory) == true)
            {
                string fullSrcDir  = Path.GetFullPath(parameters.SourceDirectory);
                string fullDestDir = Path.GetFullPath(parameters.DestinationDirectory);
                if ((parameters.DestinationDirectory.StartsWith(fullSrcDir) == false) &&
                    (parameters.SourceDirectory.StartsWith(fullDestDir) == false))
                {
                    if (ValidateOptions(options, parameters) == true)
                    {
                        Console.WriteLine("==================================================");
                        Console.WriteLine("Job started : {0}", DateTime.Now.TimeOfDay);

                        if (parameters.Name.Length > 0)
                        {
                            Console.WriteLine(parameters.Name);
                        }

                        Console.WriteLine("Synchronising source '{0}' and destination '{1}'", fullSrcDir, fullDestDir);
                        Console.WriteLine("==================================================");

                        Sync synchroniseFiles = new Sync(parameters)
                        {
                            Log = LogResult
                        };

                        if (parameters.AnalyseFirst == true)
                        {
                            // Analyse only
                            Console.WriteLine("Analysing...");
                            parameters.AnalyseOnly = true;
                            synchroniseFiles.Start();

                            if (((parameters.DirectorySynchLimit > 0) && (DirectoriesMissing > parameters.DirectorySynchLimit)) ||
                                ((parameters.FileSynchLimit > 0) && (FilesMissing > parameters.FileSynchLimit)))
                            {
                                Console.WriteLine("+++++Synchronisation limits exceeded, no synchronisation performed {0} directories {1} files",
                                                  DirectoriesMissing, FilesMissing);
                                success = ExitCode.LimitsReached;
                            }
                            else
                            {
                                // Check if any synchronisation is required
                                if ((DirectoriesMissing > 0) || (FilesMissing > 0) || (FilesChanged > 0))
                                {
                                    // Reset parameters for second pass below
                                    parameters.AnalyseOnly         = false;
                                    parameters.AnalyseFirst        = false;
                                    parameters.FileSynchLimit      = 0;
                                    parameters.DirectorySynchLimit = 0;

                                    Console.WriteLine("Synchronising...");
                                }
                                else
                                {
                                    Console.WriteLine("No synchronisation required");
                                }
                            }
                        }

                        if (parameters.AnalyseFirst == false)
                        {
                            synchroniseFiles.Start();

                            if ((DirectoriesMissing == 0) && (FilesMissing == 0) && (FilesChanged == 0))
                            {
                                Console.WriteLine("No synchronisation required");
                            }
                        }

                        Console.WriteLine("==================================================");
                        Console.WriteLine("Job finished : {0}", DateTime.Now.TimeOfDay);
                        Console.WriteLine("==================================================");
                        Console.WriteLine("");
                        Console.WriteLine("");
                    }
                    else
                    {
                        success = ExitCode.OptionError;
                    }
                }
                else
                {
                    Console.WriteLine("Error: source directory {0} and destination directory {1} cannot contain each other", fullSrcDir, fullDestDir);
                    DisplayHelp(options);
                    success = ExitCode.DirectoryError;
                }
            }
            else
            {
                Console.WriteLine("Error: source directory {0} does not exist", parameters.SourceDirectory);
                DisplayHelp(options);
                success = ExitCode.DirectoryError;
            }

            return(success);
        }