public static void WritePdbAnnotations(IndexerState state, string pdbStrPath) { foreach (SymbolFile file in state.SymbolFiles.Values) { string tmpFile = Path.GetFullPath(Path.GetTempFileName()); try { using (StreamWriter sw = File.CreateText(tmpFile)) { sw.NewLine = "\n"; if (!WriteAnnotations(state, file, sw)) continue; // Temp file is deleted in finally } ProcessStartInfo psi = new ProcessStartInfo(pdbStrPath); psi.Arguments = string.Format("-w -s:srcsrv -p:\"{0}\" -i:\"{1}\"", file.FullName, tmpFile); psi.UseShellExecute = false; psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; using (Process p = Process.Start(psi)) { p.StandardOutput.ReadToEnd(); p.StandardError.ReadToEnd(); p.WaitForExit(); } } finally { File.Delete(tmpFile); } } }
/// <summary> /// Initializes a new <see cref="SourceProvider"/> with the specified name /// </summary> /// <param name="state"></param> /// <param name="name"></param> /// <remarks>Generates a unique <see cref="Id"/> by stripping invalid chars of the name, and making it unique by adding extra characters</remarks> protected SourceProvider(IndexerState state, string name) { if (state == null) throw new ArgumentNullException("state"); _state = state; _id = name; }
/// <summary> /// SourceIndex detector which tries to find valid providers /// </summary> /// <param name="state"></param> /// <returns>true if one or more files might be managed in subversion, otherwise false</returns> public bool CanProvideSources(SharpSvn.PdbAnnotate.Framework.IndexerState state) { SortedList <string, string> directories = new SortedList <string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (SourceFile file in state.SourceFiles.Values) { string dir = file.File.DirectoryName; if (directories.ContainsKey(dir)) { continue; } directories.Add(dir, dir); if (SvnTools.IsBelowManagedPath(dir)) { return(true); } } return(false); }
/// <summary> /// /// </summary> /// <param name="state"></param> void WritePdbAnnotations(IndexerState state) { PdbWriter.WritePdbAnnotations(state, _pdbStrPath); }
void ResolveFiles(IndexerState state) { foreach (SourceResolver sp in state.Resolvers) { sp.ResolveFiles(); } }
/// <summary> /// /// </summary> /// <param name="state"></param> void ReadSourceFilesFromPdbs(IndexerState state) { PdbReader.ReadSourceFilesFromPdbs(state, _srcToolPath, ReIndexPreviouslyIndexedSymbols); }
void PerformExclusions(IndexerState state) { #region - Apply SourceRoots if (SourceRoots.Count > 0) { List<string> rootList = new List<string>(); foreach (string root in SourceRoots) { string nRoot = state.NormalizePath(root); if (!nRoot.EndsWith("\\")) nRoot += "\\"; rootList.Add(nRoot); } string[] roots = rootList.ToArray(); Array.Sort<string>(roots, StringComparer.InvariantCultureIgnoreCase); foreach (SourceFile sf in state.SourceFiles.Values) { string fileName = sf.FullName; int n = Array.BinarySearch<string>(roots, fileName, StringComparer.InvariantCultureIgnoreCase); if (n >= 0) continue; // Exact match found n = ~n; if ((n > 0) && (n <= roots.Length)) { if (fileName.StartsWith(roots[n - 1], StringComparison.InvariantCultureIgnoreCase)) continue; // Root found sf.NoSourceAvailable = true; continue; } else sf.NoSourceAvailable = true; } } #endregion - Apply SourceRoots #region - Apply ExcludeSourceRoots if (ExcludeSourceRoots.Count > 0) { List<string> rootList = new List<string>(); foreach (string root in ExcludeSourceRoots) { string nRoot = state.NormalizePath(root); if (!nRoot.EndsWith(Path.DirectorySeparatorChar.ToString())) nRoot += Path.DirectorySeparatorChar; rootList.Add(nRoot); } string[] roots = rootList.ToArray(); Array.Sort<string>(roots, StringComparer.InvariantCultureIgnoreCase); foreach (SourceFile sf in state.SourceFiles.Values) { string fileName = sf.FullName; int n = Array.BinarySearch<string>(roots, fileName, StringComparer.InvariantCultureIgnoreCase); if (n >= 0) continue; // Exact match found n = ~n; if ((n > 0) && (n <= roots.Length)) { if (fileName.StartsWith(roots[n - 1], StringComparison.InvariantCultureIgnoreCase)) sf.NoSourceAvailable = true; } } } #endregion }
IndexerResult CreateResultData(IndexerState state) { int nSources = 0; foreach (SourceFile sf in state.SourceFiles.Values) { if (sf.SourceReference != null) nSources++; } return new IndexerResult(true, state.SymbolFiles.Count, nSources, state.SourceFiles.Count, state.Resolvers.Count); }
/// <summary> /// /// </summary> /// <returns></returns> public IndexerResult Exec() { Uri codeBase = new Uri(typeof(SourceServerIndexer).Assembly.CodeBase); string myDir = Path.GetDirectoryName(codeBase.LocalPath); _srcToolPath = SvnTools.GetNormalizedFullPath(Path.Combine(myDir, "srctool.exe")); _pdbStrPath = SvnTools.GetNormalizedFullPath(Path.Combine(myDir, "pdbstr.exe")); if (!File.Exists(_srcToolPath)) throw new FileNotFoundException("SRCTOOL.EXE not found", _srcToolPath); if (!File.Exists(_srcToolPath)) throw new FileNotFoundException("PDBSTR.EXE not found", _pdbStrPath); IndexerState state = new IndexerState(); foreach (string pdbFile in SymbolFiles) { SymbolFile symbolFile = new SymbolFile(pdbFile); if (!symbolFile.Exists) throw new FileNotFoundException(string.Format("Symbol {0} file not found", symbolFile.FullName), symbolFile.FullName); state.SymbolFiles.Add(symbolFile.FullName, symbolFile); } ReadSourceFilesFromPdbs(state); // Check if there are files to index for this pdb file PerformExclusions(state); ResolveFiles(state); WritePdbAnnotations(state); return CreateResultData(state); }
static bool WriteAnnotations(IndexerState state, SymbolFile file, StreamWriter sw) { SortedList<string, SourceProvider> providers = new SortedList<string, SourceProvider>(); int itemCount = 1; foreach (SourceFile sf in file.SourceFiles) { if (!sf.IsResolved || sf.NoSourceAvailable) continue; SourceReference sr = sf.SourceReference; SourceProvider provider = sr.SourceProvider; if (providers.ContainsKey(provider.Id)) continue; providers.Add(provider.Id, provider); if (provider.SourceEntryVariableCount > itemCount) itemCount = provider.SourceEntryVariableCount; } if (providers.Count == 0) return false; sw.WriteLine("SRCSRV: ini ------------------------------------------------"); sw.WriteLine("VERSION=1"); sw.Write("VERCTRL=SharpSvn.PdbAnnotate"); foreach (SourceProvider sp in providers.Values) { if (!string.IsNullOrEmpty(sp.Name)) { sw.Write('+'); sw.Write(sp.Name); } } sw.WriteLine(); sw.WriteLine("SRCSRV: variables ------------------------------------------"); sw.WriteLine("DATETIME=" + DateTime.Now.ToUniversalTime().ToString("u")); sw.WriteLine("SRCSRVTRG=%fnvar%(%VAR2%__TRG)"); sw.WriteLine("SRCSRVCMD=%fnvar%(%VAR2%__CMD)"); //sw.WriteLine("SRCSRVENV=PATH=%PATH%\\bSystemDrive=%SystemDrive%\\bSystemRoot=%SystemRoot%\\bProgramFiles=%ProgramFiles%\\bProgramData=%ProgramData%\\b%fnvar%(%VAR2%__ENV)"); foreach (SourceProvider sp in providers.Values) { sp.WriteEnvironment(sw); } sw.WriteLine("SRCSRV: source files ---------------------------------------"); // Note: the sourcefile block must be written in the order they are found by the PdbReader // otherwise SrcTool skips all sourcefiles which don't exist locally and are out of order foreach (SourceFile sf in file.SourceFiles) { if (!sf.IsResolved || sf.NoSourceAvailable) continue; sw.Write(sf.FullName); sw.Write('*'); SourceReference sr = sf.SourceReference; SourceProvider provider = sr.SourceProvider; sw.Write(provider.Id); sw.Write('*'); string[] strings = sr.GetSourceEntries(); if (strings != null) for (int i = 0; i < itemCount; i++) { if (i < strings.Length) sw.Write(strings[i]); sw.Write('*'); } else { for (int i = 0; i < itemCount; i++) sw.Write('*'); } // Note: We defined the variables upto itemCount+2 (filename, type, itemcount), // All variables above this index are reserved for future extensions sw.WriteLine(); } sw.WriteLine("SRCSRV: end ------------------------------------------------"); return true; }
/// <summary> /// Reads all sourcefiles referenced from a PDB, and adds these to the indexerstate /// </summary> /// <param name="state"></param> /// <param name="srcToolPath"></param> /// <param name="reIndexPreviouslyIndexedSymbols"></param> public static void ReadSourceFilesFromPdbs(IndexerState state, string srcToolPath, bool reIndexPreviouslyIndexedSymbols) { List<SymbolFile> pdbsToRemove = null; foreach (SymbolFile pdb in state.SymbolFiles.Values) { ProcessStartInfo psi = new ProcessStartInfo(srcToolPath); psi.WorkingDirectory = pdb.File.DirectoryName; psi.UseShellExecute = false; psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; string output; string errors; if (!reIndexPreviouslyIndexedSymbols) { psi.Arguments = string.Format("-c \"{0}\"", pdb.FullName); using (Process p = Process.Start(psi)) { output = p.StandardOutput.ReadToEnd(); errors = p.StandardError.ReadToEnd(); p.WaitForExit(); } if (output.Contains("source files are indexed") || errors.Contains("source files are indexed") || output.Contains("source file is indexed") || errors.Contains("source file is indexed")) { // No need to change annotation; it is already indexed if (pdbsToRemove == null) pdbsToRemove = new List<SymbolFile>(); pdbsToRemove.Add(pdb); continue; } } psi.Arguments = string.Format("-r \"{0}\"", pdb.FullName); using (Process p = Process.Start(psi)) { output = p.StandardOutput.ReadToEnd(); errors = p.StandardError.ReadToEnd(); p.WaitForExit(); } if (!string.IsNullOrEmpty(errors)) { throw new SourceIndexToolException("SRCTOOL", errors.Trim()); } bool foundOne = false; foreach (string item in output.Split('\r', '\n')) { string fileName = item.Trim(); if (string.IsNullOrEmpty(fileName)) continue; // We split on \r and \n if ((fileName.IndexOf('*') >= 0) || // C++ Compiler internal file ((fileName.Length > 2) && (fileName.IndexOf(':', 2) >= 0))) { // Some compiler internal filenames of C++ start with a * // and/or have a :123 suffix continue; // Skip never existing files } if (!File.Exists(fileName)) continue; SourceFile file; if (!state.SourceFiles.TryGetValue(fileName, out file)) { file = new SourceFile(fileName); state.SourceFiles.Add(fileName, file); } pdb.AddSourceFile(file); file.AddContainer(pdb); foundOne = true; } if (!foundOne) { if (pdbsToRemove == null) pdbsToRemove = new List<SymbolFile>(); pdbsToRemove.Add(pdb); } } if (pdbsToRemove != null) { foreach (SymbolFile s in pdbsToRemove) { state.SymbolFiles.Remove(s.FullName); } } }
/// <summary> /// /// </summary> public SubversionResolver(IndexerState state) : base(state, "SVN") { //GC.KeepAlive(null); }
/// <summary> /// /// </summary> /// <param name="state"></param> /// <param name="name"></param> protected SourceResolver(IndexerState state, string name) : base(state, name) { _name = name; }