/// <summary>
        /// Deletes the log file, if it exists.
        /// </summary>
        private static void DeleteLogIfExists()
        {
            // write the name of the current class and method we are now entering, into the log
            Console.WriteLine("In LogFileManager.DeleteLogIfExists");

            Console.WriteLine(
                "LogFileManager.DeleteLogIfExists: Checking whether the folder '{0}' is writable...",
                LogFileDirectoryName);

            if (!FileAndFolderHelper.IsFolderWritable(LogFileDirectoryName))
            {
                // If we cannot write to the folder where the log file to be deleted sits in, then Heaven help us!  However the software
                // should try to work at all costs, so this method should just silently fail in this case.
                Console.WriteLine(
                    "LogFileManager.DeleteLogIfExists: The folder '{0}' is not writable, so we can't delete the log file '{1}' as requested.  Nothing to do.",
                    LogFileDirectoryName, LogFilePath);

                Console.WriteLine(
                    "LogFileManager.DeleteLogIfExists: Done.");

                return;
            }

            Console.WriteLine(
                "LogFileManager.DeleteLogIfExists: The folder '{0}' is writable, so therefore we can delete the log file '{1}'.",
                LogFileDirectoryName, LogFilePath);

            try
            {
                Console.WriteLine(
                    "LogFileManager.DeleteLogIfExists: Deleting the log file folder '{0}' and all files and folders within it, and then re-creating the folder...",
                    LogFileDirectoryName);

                if (Directory.Exists(LogFileDirectoryName))
                {
                    Directory.Delete(LogFileDirectoryName, true);
                }

                if (!Directory.Exists(LogFileDirectoryName))
                {
                    Directory.CreateDirectory(LogFileDirectoryName);
                }

                if (Directory.Exists(LogFileDirectoryName))
                {
                    Console.WriteLine(
                        "LogFileManager:DeleteLogIfExists: Successfully deleted and re-created the folder '{0}'.",
                        LogFileDirectoryName);
                }
            }
            catch (Exception e)
            {
                // dump all the exception info to the log/console
                DebugUtils.LogException(e);
            }

            Console.WriteLine("LogFileManager.DeleteLogIfExists: Done.");
        }
        /// <summary>
        /// Compresses a directory full of files into a ZIP file with the same name as the directory. Does not add the
        /// directory itself to the ZIP file.
        /// </summary>
        /// <param name="directoryPath">Path to the directory containing the files to be ZIPped.</param>
        /// <param name="zipFilePath">Path to the output ZIP file.  Must not be the same as the directory that is being ZIPped.</param>
        /// <returns></returns>
        public static bool CompressDirectory(string directoryPath, string zipFilePath)
        {
            // write the name of the current class and method we are now entering, into the log
            DebugUtils.WriteLine(DebugLevel.Debug, "In ZipperUpper.CompressDirectory");

            // Dump the variable directoryPath to the log
            DebugUtils.WriteLine(DebugLevel.Debug, "ZipperUpper.CompressDirectory: directoryPath = '{0}'", directoryPath);

            // Dump the variable zipFilePath to the log
            DebugUtils.WriteLine(DebugLevel.Debug, "ZipperUpper.CompressDirectory: zipFilePath = '{0}'", zipFilePath);

            if (!Directory.Exists(directoryPath))
            {
                // assume the directoryPath parameter specifies the release asset directory
                Console.WriteLine(Resources.ReleaseAssetDirNotFound, directoryPath);
                return(false);
            }

            if (string.IsNullOrWhiteSpace(zipFilePath))
            {
                // Oops!  There is nowhere to deposit the zip file when we're done!
                Console.WriteLine(Resources.OutputZipFilePathBlank);
                return(false);
            }

            // Check whether the zipFilePath contains characters that the operating
            // system does not allow to appear in a valid file name
            if (Path.GetFileName(zipFilePath).IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
            {
                Console.WriteLine(Resources.ReleaseZipFileNameContainsInvalidChars, zipFilePath);
                return(false);
            }

            var zipOutputFolder = Path.GetDirectoryName(zipFilePath);

            if (string.IsNullOrWhiteSpace(zipOutputFolder))
            {
                // Oops!  There is nowhere to deposit the zip file when we're done!
                Console.WriteLine(Resources.ZipOutputFolderBlank);
                return(false);
            }

            if (directoryPath.ToLower().Equals(zipOutputFolder.ToLower()))
            {
                // the output zip file is not allowed to live in the same directory as the files
                // that are being ZIPped.
                Console.WriteLine(Resources.ZipFolderMustBeDifferentFromAssetFolder);
                return(false);
            }

            /* Check whether the current user has access privileges to write to the input directory and the
             * directory where the output zip is going to live.  If the current user does not, then fail */
            if (!FileAndFolderHelper.IsFolderWritable(directoryPath))
            {
                // Current user does not have write access privileges to the input folder.
                Console.WriteLine(Resources.UserNotHasPermissionsToFolder, directoryPath);
                return(false);
            }

            /* Create the folder where the outputted ZIP file is going to live, if that folder
             * does not already exist. */
            FileAndFolderHelper.CreateDirectoryIfNotExists(
                zipOutputFolder
                );

            if (!FileAndFolderHelper.IsFolderWritable(zipOutputFolder))
            {
                // Current user does not have write access privileges to the output folder.
                Console.WriteLine(Resources.UserNotHasPermissionsToFolder, zipOutputFolder);
                return(false);
            }

            // Delete the output file if it already exists.
            if (File.Exists(zipFilePath))
            {
                File.Delete(zipFilePath);
            }

            try
            {
                var events = new FastZipEvents();

                // try to keep going even if a particular file or folder fails
                events.FileFailure      += (s1, a1) => a1.ContinueRunning = true;
                events.DirectoryFailure += (s2, a2) => a2.ContinueRunning = true;
                //events.CompletedFile += (s3, a3) => Console.WriteLine($"Finished file '{a3.Name}.");
                //events.ProcessFile += (s4, a4) => Console.WriteLine($"Zipping file {a4.Name}...");

                new FastZip(events)
                .CreateZip(
                    zipFilePath,
                    directoryPath,
                    true,
                    string.Empty);
            }
            catch (Exception e)
            {
                // dump all the exception info to the log
                DebugUtils.LogException(e);

                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }

                return(false);
            }

            return(File.Exists(zipFilePath)); // operation succeeded if the zip file exists at the path the user wants it at.
        }
        /// <summary>
        /// Initializes the application's logging subsystem.
        /// </summary>
        /// <param name="muteDebugLevelIfReleaseMode">Set to true if we should not write out "DEBUG" messages to the log file when in the NewRelease mode.  Set to false if all messages should always be logged.</param>
        /// <param name="overwrite">Overwrites any existing logs for the application with the latest logging sent out by this instance.</param>
        /// <param name="configurationFilePathname">Specifies the path to the configuration file to be utilized for initializing log4net.  If blank, the system attempts to utilize the default App.config file.</param>
        /// <remarks>Upon completion, this method sets the <see cref="IsLoggingInitialized"/> property.  Applications should check the value of this
        /// property to determine whether logging succeeded.</remarks>
        public static void InitializeLogging(bool muteDebugLevelIfReleaseMode = true,
                                             bool overwrite = true, string configurationFilePathname = "")
        {
            // write the name of the current class and method we are now entering, into the log
            Console.WriteLine("In LogFileManager.InitializeLogging");

            // Check whether the path to the configuration file is blank; or, if it's not blank, whether the specified file actually exists at the path indicated.
            // If the configuration file pathname is blank and/or it does not exist at the path indicated, then call the version of XmlConfigurator.Configure that does
            // not take any arguments.  On the other hand, if the configurationFilePathname parameter is not blank, and it specifies a file that actually does exist
            // at the specified path, then pass that path to the XmlConfigurator.Configure method.
            if (string.IsNullOrWhiteSpace(configurationFilePathname) ||
                !File.Exists(configurationFilePathname))
            {
                // If the file specified by the configurationFilePathname does not actually exist, the author of this software
                // needs to know about it, so throw a FileNotFoundException
                if (!string.IsNullOrWhiteSpace(configurationFilePathname) && // only do this check for a non-blank file name.
                    !File.Exists(configurationFilePathname))
                {
                    Console.WriteLine(
                        $"The file '{configurationFilePathname}' was not found.\n\nThe application needs this file in order to continue.");
                    IsLoggingInitialized = false;
                    return;
                }

                XmlConfigurator.Configure();
            }
            else
            {
                XmlConfigurator.Configure(new FileInfo(configurationFilePathname));
            }

            // Check to see if the required property, LogFilePath, is blank, whitespace, or null. If it is any of these, send an
            // error to the log file and quit.

            if (string.IsNullOrWhiteSpace(LogFilePath))
            {
                // if we are here, then the call above did not work, try to load the configuration from the
                // .exe.config file which may have been included as an embedded resource.
                if (!ConfigureLogFileFromEmbeddedResource())
                {
                    Console.WriteLine("LogFileManager.InitializeLogging: Failed to initialize logging from embedded configuration file.");
                    return;
                }
            }

            // If we are here, then the required string property, LogFilePath, has a value.  Check to ensure that the
            // LogFileDirectoryName read-only property also has a value, which should be the path to the folder in which
            // the log file lives.
            if (string.IsNullOrWhiteSpace(LogFileDirectoryName))
            {
                return;
            }

            // Check whether the parent folder of the folder in which the log file will live, is also writable by the
            // currently-logged-in user
            var directoryInfo = new DirectoryInfo(LogFileDirectoryName).Parent;

            if (directoryInfo != null)
            {
                // Check whether the user has write permissions on the directory tree that will
                // contain the log files.  Stop if the user does not.
                var logFileDirectoryParent = directoryInfo
                                             .FullName;

                // Dump the variable logFileDirectoryParent to the log
                Console.WriteLine("LogFileManager.InitializeLogging: logFileDirectoryParent = '{0}'", logFileDirectoryParent);

                Console.WriteLine(
                    "LogFileManager.InitializeLogging: Checking whether the user has write-level access to the folder '{0}'...",
                    logFileDirectoryParent);

                // Check if the user has write access to the parent directory of the log file.
                if (!FileAndFolderHelper.IsFolderWritable(logFileDirectoryParent))
                {
                    Console.WriteLine(
                        @"LogFileManager.InitializeLogging: The user '{0}\{1}' does not have write-level access to the folder '{2}'.",
                        Environment.UserDomainName,
                        Environment.UserName,
                        logFileDirectoryParent);

                    // Mark the IsLoggingInitialized property to false
                    IsLoggingInitialized = false;

                    return;
                }
            }

            // Check whether the log file directory already exists.  If not, then try to create it.
            FileAndFolderHelper.CreateDirectoryIfNotExists(LogFileDirectoryName);

            // We have to insist that the directory that the log file is in is writable.  If we can't
            // get write access to the log file directory, then throw an exception.
            if (!FileAndFolderHelper.IsFolderWritable(LogFileDirectoryName))
            {
                Console.WriteLine(
                    $"The current user does not have write permissions to the directory '{LogFileDirectoryName}'.");

                IsLoggingInitialized = false;
            }

            // Set options on the file appender of the logging system to minimize locking issues
            FileAppenderConfigurator.SetMinimalLock(FileAppenderManager.GetFirstFileAppender());

            // If the overwrite parameter's value is set to true, then overwrite the log -- that is,
            // delete any existing log file that may already exist.
            if (overwrite)
            {
                DeleteLogIfExists();
            }

            // initialization succeeded
            IsLoggingInitialized = true;

            // Set up the Event Log and the DebugUtils objects.
            // Attempt to get a name for the executing application.
            DebugUtils.ApplicationName = GetDebugApplicationName();

            // If we found a value for the ApplicationName, then initialize the EventLogManager.  The EventLogManager
            // is a companion component to DebugUtils which also spits out logging to the System Event Log.  This is handy
            // in the case where the user does not have write access to the C:\ProgramData directory, for example.
            if (!string.IsNullOrWhiteSpace(DebugUtils.ApplicationName))
            {
                EventLogManager.Instance.Initialize(DebugUtils.ApplicationName, EventLogType.Application);
            }

            // Set up the DebugUtils object with values that specify how we want logging done.  Be sure to specify that
            // we should not write log messages to the console under any circumstances, since this is a console application
            // that may be interactive to the user or have its stdout results parsed by another program.
            SetUpDebugUtils(muteDebugLevelIfReleaseMode, true, false, 1, true);

            // done
        }
Esempio n. 4
0
        /// <summary>
        /// Uploads the assets in the release asset directory individually to the newly-created release.   Flattens any directory structure that might exist in the
        /// folder referred to by <see cref="releaseAssetDir"/>.
        /// </summary>
        /// <param name="releaseAssetDir">String containing the fully-qualified path to the directory containing release assets to be uploaded.</param>
        /// <param name="newRelease">Reference to an instance of a dynamic object which has been deserialized from the response JSON
        /// of the call to create the new release.</param>
        /// <param name="userAccessToken">String containing the user's API access token.</param>
        public static void UploadAssetsIndividually(string releaseAssetDir,
                                                    dynamic newRelease, string userAccessToken)
        {
            if (string.IsNullOrWhiteSpace(releaseAssetDir))
            {
                throw new ArgumentNullException(nameof(releaseAssetDir));
            }

            if (!Directory.Exists(releaseAssetDir))
            {
                throw new DirectoryNotFoundException(string.Format(Resources.DirectoryNotFound, releaseAssetDir));
            }

            if (newRelease == null)
            {
                throw new ArgumentNullException(nameof(newRelease));
            }

            if (string.IsNullOrWhiteSpace(userAccessToken))
            {
                throw new ArgumentNullException(nameof(userAccessToken));
            }

            // Iterate over all the files in the release asset directory and its subdirectories,
            // one by one.  Flatten the directory tree into just a big ol' list of files.  To preserve
            // the directory tree, distribute the release assets in ZIP format and then have your
            // Setup program un zip the assets into their directory structure.
            foreach (var assetFile in FileSearcher.GetAllFilesInFolder(
                         releaseAssetDir).Where(fsi => (fsi.Attributes & FileAttributes.Directory)
                                                != FileAttributes.Directory))
            {
                /* Make a new request each iteration of the loop over asset files */
                var request = GitHubRequestFactory.PrepareGitHubRequest(Method.POST, userAccessToken);

                // Get just the name and extension of the asset for use in the
                // upload url later.  If blank is returned, then something went wrong.
                // In that case, just skip the current file.
                var assetFileName = Path.GetFileName(assetFile.FullName);
                if (string.IsNullOrWhiteSpace(assetFileName))
                {
                    continue;
                }

                // If the file has zero bytes of length, do not upload it
                if (FileAndFolderHelper.FileHasZeroLength((FileInfo)assetFile))
                {
                    Console.WriteLine(
                        $"ERROR: File '{assetFileName}' has zero bytes of length.  Not uploading it.");
                    // Just skip files that have zero length
                    continue;
                }

                /* From Tavis.UriTemplates NuGet package -- works like Ruby uri_template gem */
                var uploadUrl = new UriTemplate(newRelease.upload_url.Value)
                                .AddParameters(new
                {
                    name  = assetFileName,
                    label = assetFileName
                })
                                .Resolve();
                if (string.IsNullOrWhiteSpace(uploadUrl))
                {
                    Console.WriteLine(Resources.UploadUrlNotObtainable);
                    Environment.Exit(Resources.ERROR_NOT_OBTAINED_RELEASE_UPLOAD_URL);
                }

                // Prepare a REST request with the upload url from the create release API response
                // above
                var client = new RestClient(
                    uploadUrl
                    );

                var assetMimeMapping = MimeMapping.GetMimeMapping(assetFile.FullName);
                request.AddHeader(Resources.ContentTypeHeaderName,
                                  assetMimeMapping
                                  );

                var bytes = File.ReadAllBytes(assetFile.FullName);
                if (!bytes.Any())
                {
                    continue;   // zero-length file
                }
                request.AddHeader("Content-Length", bytes.Length.ToString());
                Console.WriteLine($"{bytes.Length} bytes read from file '{assetFile.FullName}'. Uploading...");

                request.AddParameter(
                    assetMimeMapping, bytes, ParameterType.RequestBody
                    );

                var response = client.Execute(request);

                if (response == null || response.StatusCode != HttpStatusCode.Created)
                {
                    Console.WriteLine(Resources.FailedToUploadAsset, assetFileName);
                    Environment.Exit(Resources.ERROR_ASSET_NOT_ACCEPTED);
                }
                else
                {
                    Console.WriteLine(Resources.AssetAccepted, assetFileName);
                }
            }
        }