Exemple #1
0
        private static int Main()
        {
            Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            ConsoleHelper.FixEncoding();

            List<string> assemblyFileNames = new List<string>();

            CommandLineHelper cmdLine = new CommandLineHelper();
            var debugOption = cmdLine.RegisterOption("debug").Alias("d");
            var helpOption = cmdLine.RegisterOption("help").Alias("h", "?");
            var noGzOption = cmdLine.RegisterOption("nogz");
            var noNamesOption = cmdLine.RegisterOption("nonames");
            var optimizeOption = cmdLine.RegisterOption("optimize").Alias("opt");
            var outFileOption = cmdLine.RegisterOption("outfile", 1).Alias("o");
            var srcBaseOption = cmdLine.RegisterOption("srcbase", 1);

            try
            {
                cmdLine.Parse();
            }
            catch (Exception ex)
            {
                return ConsoleHelper.ExitError(ex.Message, 1);
            }

            if (helpOption.IsSet)
            {
                ShowHelp();
                return 0;
            }

            try
            {
                foreach (var arg in cmdLine.FreeArguments)
                {
                    if (arg.IndexOfAny(new[] { '?', '*' }) != -1)
                    {
                        foreach (string foundFile in Directory.GetFiles(Path.GetDirectoryName(arg), Path.GetFileName(arg)))
                        {
                            CheckAddAssemblyFile(assemblyFileNames, foundFile);
                        }
                    }
                    else
                    {
                        CheckAddAssemblyFile(assemblyFileNames, arg);
                    }
                }
            }
            catch (Exception ex)
            {
                return ConsoleHelper.ExitError("Cannot load input files. " + ex.Message, 5);
            }

            if (assemblyFileNames.Count == 0)
            {
                return ConsoleHelper.ExitError("Missing argument: Input assembly file name", 2);
            }

            if (debugOption.IsSet)
            {
                ConsoleHelper.WriteLine("Input assemblies:", ConsoleColor.DarkGray);
                foreach (string fileName in assemblyFileNames)
                {
                    ConsoleHelper.WriteLine("  " + fileName, ConsoleColor.DarkGray);
                }
            }

            XmlDocument doc = new XmlDocument();
            XmlWriter xw = doc.CreateNavigator().AppendChild();
            PdbReader reader = new PdbReader(assemblyFileNames, xw);
            if (srcBaseOption.IsSet)
            {
                reader.SourceBasePath = Path.GetFullPath(srcBaseOption.Value);
            }
            try
            {
                reader.Convert();
            }
            catch (System.Reflection.ReflectionTypeLoadException ex)
            {
                if (ex.LoaderExceptions != null)
                {
                    ConsoleHelper.WriteLine("ReflectionTypeLoadException.LoaderExceptions:", ConsoleColor.Red);
                    foreach (var ex2 in ex.LoaderExceptions)
                    {
                        ConsoleHelper.WriteWrapped("- " + ex2.Message);
                    }
                }
                return ConsoleHelper.ExitError("Cannot convert symbols. " + ex.Message, 3);
            }
            catch (Exception ex)
            {
                return ConsoleHelper.ExitError("Cannot convert symbols. " + ex.Message, 3);
            }
            xw.Close();

            if (optimizeOption.IsSet)
            {
                // Reduce multiple subsequent "hidden" sequence points to the first of them
                doc.SelectNodes("/symbols/module/methods/method/sequencePoints/entry[@hidden='true'][preceding-sibling::entry[1][@hidden='true']]")
                    .OfType<XmlNode>()
                    .ForEachSafe(n => n.ParentNode.RemoveChild(n));

                // Remove sequence points if they are all hidden
                doc.SelectNodes("/symbols/module/methods/method/sequencePoints[not(entry[@startLine])]")
                    .OfType<XmlNode>()
                    .ForEachSafe(n => n.ParentNode.RemoveChild(n));

                // Remove all methods with no sequence points
                doc.SelectNodes("/symbols/module/methods/method[not(sequencePoints)]")
                    .OfType<XmlNode>()
                    .ForEachSafe(n => n.ParentNode.RemoveChild(n));

                // Remove all files with no remaining methods
                doc.SelectNodes("/symbols/module/files/file")
                    .OfType<XmlNode>()
                    .ForEachSafe(n =>
                    {
                        if (n.SelectNodes("../../methods/method/sequencePoints/entry[@fileRef='" + n.Attributes["id"].Value + "']").Count == 0)
                        {
                            n.ParentNode.RemoveChild(n);
                        }
                    });
            }

            if (noNamesOption.IsSet)
            {
                // Remove all name attributes from methods
                doc.SelectNodes("/symbols/module/methods/method")
                    .OfType<XmlNode>()
                    .ForEachSafe(n => n.Attributes.RemoveNamedItem("name"));
            }

            string xmlFileName =
                outFileOption.Value ??
                Path.ChangeExtension(
                    assemblyFileNames.OrderBy(a => Path.GetExtension(a).Equals(".dll", StringComparison.OrdinalIgnoreCase)).First(),
                    (noGzOption.IsSet ? ".pdb.xml" : ".pdbx"));

            if (debugOption.IsSet)
            {
                ConsoleHelper.WriteLine("Output file:", ConsoleColor.DarkGray);
                ConsoleHelper.WriteLine("  " + xmlFileName, ConsoleColor.DarkGray);
            }

            try
            {
                if (!noGzOption.IsSet)
                {
                    using (FileStream fileStream = new FileStream(xmlFileName, FileMode.Create))
                    using (GZipStream gzStream = new GZipStream(fileStream, CompressionMode.Compress))
                    {
                        doc.Save(gzStream);
                    }
                }
                else
                {
                    doc.Save(xmlFileName);
                }
            }
            catch (Exception ex)
            {
                return ConsoleHelper.ExitError("Cannot save XML file. " + ex.Message, 4);
            }
            return 0;
        }
Exemple #2
0
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            // Fix WPF's built-in themes
            if (OSInfo.IsWindows8OrNewer)
            {
                ReAddResourceDictionary("/Resources/RealWindows8.xaml");
            }

            // Initialise and show the main window

            CommandLineHelper cmdLine = new CommandLineHelper();
            var scanOption = cmdLine.RegisterOption("scan", 1).Alias("s");

            try
            {
                cmdLine.Parse();
            }
            catch (Exception ex)
            {
                App.ErrorMessage("Command line error.", ex, "Parsing command line");
                Application.Current.Shutdown();
            }

            List<string> filesToLoad = new List<string>();
            bool error = false;
            foreach (string fileNameArg in cmdLine.FreeArguments)
            {
                if (!string.IsNullOrWhiteSpace(fileNameArg))
                {
                    // File name
                    if (File.Exists(fileNameArg))
                    {
                        // File exists, open it
                        string fileName = fileNameArg;
                        if (!Path.IsPathRooted(fileName))
                        {
                            fileName = Path.GetFullPath(fileName);
                        }
                        filesToLoad.Add(fileName);
                    }
                    else if (Directory.Exists(fileNameArg))
                    {
                        // Directory specified, collect all files
                        foreach (string fileName in Directory.GetFiles(fileNameArg, "*.txd"))
                        {
                            filesToLoad.Add(fileName);
                        }
                        if (filesToLoad.Count == 0)
                        {
                            // Nothing found, try older XML file names
                            foreach (string fileName in Directory.GetFiles(fileNameArg, "*.xml"))
                            {
                                if (FileNameHelper.GetCulture(fileName) != null)
                                {
                                    filesToLoad.Add(fileName);
                                }
                            }
                        }
                    }
                    else
                    {
                        FL.Error("File/directory not found", fileNameArg);
                        error = true;
                    }
                }
            }
            if (error)
            {
                App.ErrorMessage("At least one of the files or directories specified at the command line could not be found.");
            }

            // Scan for other files near the selected files
            // (Currently only active if a single file is specified)
            //if (filesToLoad.Count == 1)
            //{
            //    foreach (string fileName in filesToLoad.Distinct().ToArray())
            //    {
            //        if (fileName.ToLowerInvariant().EndsWith(".txd") && File.Exists(fileName))
            //        {
            //            // Existing .txd file
            //            // Scan same directory for other .txd files
            //            string[] otherFiles = Directory.GetFiles(Path.GetDirectoryName(fileName), "*.txd");
            //            // otherFiles should contain fileName and may contain additional files
            //            if (otherFiles.Length > 1)
            //            {
            //                if (App.YesNoQuestion("Other Tx dictionary files are located in the same directory as the selected file. Should they also be loaded?"))
            //                {
            //                    // Duplicates will be removed later
            //                    filesToLoad.AddRange(otherFiles);
            //                }
            //            }
            //        }
            //    }
            //}
            // NOTE: Loading multiple txd files is not supported. (Only scan for more cultures of version 1 files. - Done)

            if (!FileNameHelper.FindOtherCultures(filesToLoad))
                Application.Current.Shutdown();

            // Create main window and view model
            var view = new MainWindow();
            var viewModel = new MainViewModel();

            if (filesToLoad.Count == 0 && scanOption.IsSet)
            {
                viewModel.ScanDirectory = scanOption.Value;
            }

            view.DataContext = viewModel;

            // Load selected files
            if (filesToLoad.Count > 0)
            {
                viewModel.LoadFiles(filesToLoad);
            }

            // Show the main window
            view.Show();
        }
        /// <summary>
        /// Wrapped main program, uses <see cref="ConsoleException"/> as return code in case of
        /// error and does not wait at the end.
        /// </summary>
        private static void MainWrapper()
        {
            CommandLineHelper cmdLine = new CommandLineHelper();
            var showHelpOption = cmdLine.RegisterOption("help").Alias("h", "?");
            var showVersionOption = cmdLine.RegisterOption("version").Alias("ver");
            var debugOption = cmdLine.RegisterOption("debug");
            var patchAssemblyInfoOption = cmdLine.RegisterOption("patch");
            var restorePatchedFilesOption = cmdLine.RegisterOption("restore");
            var simpleAttributeOption = cmdLine.RegisterOption("simple");
            var informationalAttributeOption = cmdLine.RegisterOption("info");
            var allAttributesOption = cmdLine.RegisterOption("all");
            var formatOption = cmdLine.RegisterOption("format", 1);
            var revisionOnlyOption = cmdLine.RegisterOption("revonly");
            var requireVcsOption = cmdLine.RegisterOption("require", 1);
            var rejectModifiedOption = cmdLine.RegisterOption("rejectmod").Alias("rejectmodified");
            var rejectMixedOption = cmdLine.RegisterOption("rejectmix").Alias("rejectmixed");
            var multiProjectOption = cmdLine.RegisterOption("multi");
            var scanRootOption = cmdLine.RegisterOption("root");
            var decodeRevisionOption = cmdLine.RegisterOption("decode", 1);
            var predictRevisionsOption = cmdLine.RegisterOption("predict");

            try
            {
                //cmdLine.ReadArgs(Environment.CommandLine, true);   // Alternative split method, should have the same result
                cmdLine.Parse();
                showDebugOutput = debugOption.IsSet;
                if (showDebugOutput)
                {
                    ShowDebugMessage(
                        "Command line: " +
                            Environment.GetCommandLineArgs()
                                .Select(s => "[" + s + "]")
                                .Aggregate((a, b) => a + " " + b));
                }
            }
            catch (Exception ex)
            {
                throw new ConsoleException(ex.Message, ExitCodes.CmdLineError);
            }

            // Handle simple text output options
            if (showHelpOption.IsSet)
            {
                ShowHelp();
                return;
            }
            if (showVersionOption.IsSet)
            {
                ShowVersion();
                return;
            }

            // Check for environment variable from PowerShell build framework.
            // If psbuild has set this variable, it is using NetRevisionTool itself in multi-project
            // mode and pre/postbuild actions in individual projects should not do anything on their
            // own.
            if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SuppressNetRevisionTool")))
            {
                ShowDebugMessage("SuppressNetRevisionTool environment variable is set. Quitting…");
                return;
            }

            // Find all directories
            string path = GetWorkPath(cmdLine);
            string[] projectDirs = null;
            if (multiProjectOption.IsSet)
            {
                // Read solution file and collect all projects
                projectDirs = GetProjectsFromSolution(path);

                // From now on, work with the solution directory as default path to get the revision of
                if (Path.GetExtension(path).ToLowerInvariant() == ".sln")
                {
                    path = Path.GetDirectoryName(path);
                }
            }
            else
            {
                if (!Directory.Exists(path))
                    throw new ConsoleException("The specified project directory does not exist.", ExitCodes.FileNotFound);

                projectDirs = new[] { path };
            }

            // Restoring doesn't need more info, do it now
            if (restorePatchedFilesOption.IsSet)
            {
                // Restore AssemblyInfo file(s)
                foreach (string projectDir in projectDirs)
                {
                    var aih = new AssemblyInfoHelper(projectDir, true);
                    aih.RestoreFile();
                }
                return;
            }

            // Analyse working directory
            RevisionData data = ProcessDirectory(path, scanRootOption.IsSet, requireVcsOption.Value);
            data.Normalize();

            // Check for required VCS
            if (requireVcsOption.IsSet)
            {
                if (data.VcsProvider == null ||
                    !data.VcsProvider.Name.Equals(requireVcsOption.Value, StringComparison.OrdinalIgnoreCase))
                {
                    throw new ConsoleException("Required VCS \"" + requireVcsOption.Value + "\" not present.", ExitCodes.RequiredVcs);
                }
            }

            // Check for reject modifications/mixed revisions
            if (rejectModifiedOption.IsSet && data.IsModified)
            {
                throw new ConsoleException("The working directory contains uncommitted modifications.", ExitCodes.RejectModified);
            }
            if (rejectMixedOption.IsSet && data.IsMixed)
            {
                throw new ConsoleException("The working directory contains mixed revisions.", ExitCodes.RejectMixed);
            }

            // Determine revision ID format, in case we need one here
            string format = null;
            if (formatOption.IsSet && !string.IsNullOrWhiteSpace(formatOption.Value))
            {
                // Take from command-line option
                format = formatOption.Value;
                ShowDebugMessage("Format specified: " + format);
            }
            else
            {
                // None or empty specified. Search in AssemblyInfo file(s) in the project(s)
                ShowDebugMessage("No format specified, searching AssemblyInfo source file.");
                AssemblyInfoHelper aih = null;
                foreach (string projectDir in projectDirs)
                {
                    aih = new AssemblyInfoHelper(projectDir, false);
                    if (aih.FileExists)
                    {
                        format = aih.GetRevisionFormat();
                        if (format != null)
                        {
                            if (projectDirs.Length > 1)
                            {
                                ShowDebugMessage("Found format in project \"" + projectDir + "\".");
                            }
                            break;
                        }
                    }
                    else
                    {
                        ShowDebugMessage("  AssemblyInfo source file not found.", 2);
                    }
                }
                if (format != null)
                {
                    ShowDebugMessage("Found format: " + format);
                }
            }

            if (format == null)
            {
                if (data.RevisionNumber > 0)
                {
                    ShowDebugMessage("No format available, using default format for revision number.");
                    format = "{revnum}";
                }
                else if (!string.IsNullOrEmpty(data.CommitHash) && !Regex.IsMatch(data.CommitHash, "^0+$"))
                {
                    ShowDebugMessage("No format available, using default format for commit hash.");
                    format = "{chash:8}";
                }
                else
                {
                    ShowDebugMessage("No format available, using empty format.");
                    format = "";
                }
            }

            if (decodeRevisionOption.IsSet)
            {
                // Decode specified revision ID
                RevisionFormat.ShowDecode(format, decodeRevisionOption.Value);
            }
            else if (predictRevisionsOption.IsSet)
            {
                // Predict next revision IDs
                RevisionFormat.PredictValue(format);
            }
            else if (patchAssemblyInfoOption.IsSet)
            {
                // Patch AssemblyInfo file(s)
                bool noAttrSet = !simpleAttributeOption.IsSet && !informationalAttributeOption.IsSet;
                bool simpleAttributes = simpleAttributeOption.IsSet || noAttrSet;
                bool informationalAttribute = informationalAttributeOption.IsSet || noAttrSet;

                foreach (string projectDir in projectDirs)
                {
                    var aih = new AssemblyInfoHelper(projectDir, true);
                    aih.PatchFile(format, data, simpleAttributes, informationalAttribute, revisionOnlyOption.IsSet);
                }
            }
            else
            {
                // Just display revision ID
                var rf = new RevisionFormat();
                rf.RevisionData = data;
                Console.WriteLine(rf.Resolve(format));
            }
        }
Exemple #4
0
        /// <summary>
        /// Wrapped main program, uses <see cref="ConsoleException"/> as return code in case of
        /// error and does not wait at the end.
        /// </summary>
        private static void MainWrapper()
        {
            CommandLineHelper cmdLine = new CommandLineHelper();
            var showHelpOption = cmdLine.RegisterOption("help").Alias("h", "?");
            var showVersionOption = cmdLine.RegisterOption("version").Alias("ver");
            var debugOption = cmdLine.RegisterOption("debug");
            var utf8Option = cmdLine.RegisterOption("utf8");
            var utf16Option = cmdLine.RegisterOption("utf16");
            var utf8NoBomOption = cmdLine.RegisterOption("utf8nobom");
            var defaultEncodingOption = cmdLine.RegisterOption("defaultenc");

            try
            {
                //cmdLine.ReadArgs(Environment.CommandLine, true);   // Alternative split method, should have the same result
                cmdLine.Parse();
                showDebugOutput = debugOption.IsSet;
                if (showDebugOutput)
                {
                    ShowDebugMessage(
                        "Command line: " +
                            Environment.GetCommandLineArgs()
                                .Select(s => "[" + s + "]")
                                .Aggregate((a, b) => a + " " + b));
                }
            }
            catch (Exception ex)
            {
                throw new ConsoleException(ex.Message, ExitCodes.CmdLineError);
            }

            // Handle simple text output options
            if (showHelpOption.IsSet)
            {
                ShowHelp();
                return;
            }
            if (showVersionOption.IsSet)
            {
                ShowVersion();
                return;
            }

            if (cmdLine.FreeArguments.Length < 2)
            {
                throw new ConsoleException("Too few arguments.", ExitCodes.CmdLineError);
            }

            // Prepare arguments
            string fileName = cmdLine.FreeArguments[0];
            string targetName = cmdLine.FreeArguments[1];

            Encoding encoding = null;
            if (utf8Option.IsSet) encoding = Encoding.UTF8;
            if (utf16Option.IsSet) encoding = Encoding.Unicode;
            if (utf8NoBomOption.IsSet) encoding = new UTF8Encoding(false);
            if (defaultEncodingOption.IsSet) encoding = Encoding.Default;

            Dictionary<string, string> data = new Dictionary<string, string>();
            for (int i = 2; i < cmdLine.FreeArguments.Length; i++)
            {
                string arg = cmdLine.FreeArguments[i];
                string[] parts = arg.Split(new[] { '=' }, 2);
                if (parts.Length < 2)
                {
                    throw new ConsoleException("Invalid name value pair specification in argument " + (i + 1) + ".", ExitCodes.CmdLineError);
                }
                if (data.ContainsKey(parts[0]))
                {
                    throw new ConsoleException("Duplicate name value pair specification in argument " + (i + 1) + ".", ExitCodes.CmdLineError);
                }
                data[parts[0]] = parts[1];
            }

            // Replace data in file
            ReplaceHelper rh = new ReplaceHelper(fileName, encoding);
            rh.ReplaceData(targetName, data);
        }
 /// <summary>
 /// Gets the work path from the command line or the current directory.
 /// </summary>
 /// <param name="cmdLine">Command line.</param>
 /// <returns>The work path.</returns>
 private static string GetWorkPath(CommandLineHelper cmdLine)
 {
     string path = Environment.CurrentDirectory;
     if (cmdLine.FreeArguments.Length > 0)
     {
         // Trim quotes, they can appear for mysterious reasons from VS/MSBuild
         path = cmdLine.FreeArguments[0].Trim(' ', '"');
         if (!Path.IsPathRooted(path))
         {
             path = Path.GetFullPath(path);
         }
         // Remove all trailing directory separators to make it safer
         path = path.TrimEnd('/', '\\');
     }
     else
     {
         ShowDebugMessage("No path specified, using current directory.");
     }
     ShowDebugMessage("Input directory: " + path);
     return path;
 }