/// ------------------------------------------------------------------------------------ /// <summary> /// Resolve references of a reference /// </summary> /// <param name="referencePath">Path to the referenced assembly</param> /// ------------------------------------------------------------------------------------ private void ResolveReferences(string referencePath) { string referenceName = Path.GetFileName(referencePath); XmlAssembly assembly = m_cache[referenceName]; if (assembly != null) { // we have cached references for this assembly foreach (Reference reference in assembly.References) { string srcFilePath = Path.Combine(ToDirectory.FullName, reference.Name); string dstFilePath = Path.Combine(m_dstBaseInfo.FullName, Path.GetFileName(reference.Name)); if ((IsUnix && srcFilePath != dstFilePath) || (!IsUnix && srcFilePath.ToLower() != dstFilePath.ToLower())) { FileCopyMap[dstFilePath] = new FileDateInfo(IsUnix ? srcFilePath : srcFilePath.ToLower(), DateTime.MinValue); AddFile(srcFilePath, "xml"); AddFile(srcFilePath, "pdb"); ResolveReferences(srcFilePath); } } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> with the specified value to the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> . /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to add.</param> /// <returns>The index at which the new element was inserted.</returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.AddRange( /// SIL.FieldWorks.Build.Tasks.XmlAssembly[])'/> /// ------------------------------------------------------------------------------------ public int Add(XmlAssembly value) { if (List.Contains(value)) { List.Remove(value); } m_Hashtable[value.AssemblyName] = value; return(List.Add(value)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> into the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> at the specified index. /// </summary> /// <param name='index'>The zero-based index where <paramref name='value'/> should be inserted.</param> /// <param name=' value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to insert.</param> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.Add'/> /// ------------------------------------------------------------------------------------ public void Insert(int index, XmlAssembly value) { if (List.Contains(value)) { List.Remove(value); } List.Insert(index, value); m_Hashtable[value.AssemblyName] = value; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines whether the specified assembly is equal to the current assembly /// </summary> /// <param name="obj">The assembly to compare with the current assembly</param> /// <returns><c>true</c> if the assemblies are the same, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ public override bool Equals(object obj) { XmlAssembly assembly = obj as XmlAssembly; if (assembly != null) { return(assembly.AssemblyName == AssemblyName); } return(false); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Add the referenced assembly to the list of assemblies, resolve any referenced /// assemblies, and add the XML and PDB files. /// </summary> /// <param name="xmlAssembly">The assembly</param> /// <param name="referenceName">The name (and path) of the referenced assembly</param> /// ------------------------------------------------------------------------------------ private void AddAssemblyAndRelatedFiles(XmlAssembly xmlAssembly, string referenceName) { string srcFilePath = referenceName.StartsWith(ToDirectory.FullName) ? referenceName.Substring(ToDirectory.FullName.Length + 1) : referenceName; xmlAssembly.Add(srcFilePath); if (m_fResolveAssemblies) { ResolveReferences(referenceName); } AddFile(referenceName, "xml"); AddFile(referenceName, "pdb"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Check for circular references /// </summary> /// ------------------------------------------------------------------------------------ protected override void ExecuteTask() { LoadReferences(); Log(Level.Verbose, "Checking references"); Hashtable states = new Hashtable(); Stack visiting = new Stack(); TargetCollection targets = Project.TopologicalTargetSort(Project.DefaultTargetName, Project.Targets); // loop through all targets - backwards, because top level gets build at the end // we do it in hierarchical order, so that we get the same result regardless of the // order of assemblies in references.xml for (int i = targets.Count - 1; i >= 0; i--) { // find assembly that corresponds to target Target target = (Target)targets[i]; XmlAssembly assembly = null; if (target.Name.ToLower().EndsWith("exe")) { // TeExe -> Te.Exe string assemblyName = target.Name.Insert(target.Name.Length - 3, "."); assembly = m_Cache.Assemblies[assemblyName]; } if (assembly == null) { // TeDll -> TeDll.dll assembly = m_Cache.Assemblies[target.Name + ".dll"]; if (assembly == null) { // Te -> Te.exe assembly = m_Cache.Assemblies[target.Name + ".exe"]; } } if (!CheckAssembly(assembly, states, visiting)) { break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> with the specified value to the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> . /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to add.</param> /// <returns>The index at which the new element was inserted.</returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.AddRange( /// SIL.FieldWorks.Build.Tasks.XmlAssembly[])'/> /// ------------------------------------------------------------------------------------ public int Add(XmlAssembly value) { if (List.Contains(value)) List.Remove(value); m_Hashtable[value.AssemblyName] = value; return List.Add(value); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Removes a specific <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> from the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> . /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to remove from the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> .</param> /// <exception cref='System.ArgumentException'><paramref name='value'/> is not found in the Collection. </exception> /// ------------------------------------------------------------------------------------ public void Remove(XmlAssembly value) { List.Remove(value); m_Hashtable.Remove(value.AssemblyName); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> containing any array of <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> objects. /// </summary> /// <param name='value'> /// A array of <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> objects with which to intialize the collection /// </param> /// ------------------------------------------------------------------------------------ public XmlAssemblyCollection(XmlAssembly[] value) { this.AddRange(value); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Returns the index of a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> in /// the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> . /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to locate.</param> /// <returns> /// The index of the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> of <paramref name='value'/> in the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/>, if found; otherwise, -1. /// </returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.Contains'/> /// ------------------------------------------------------------------------------------ public int IndexOf(XmlAssembly value) { return List.IndexOf(value); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> into the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> at the specified index. /// </summary> /// <param name='index'>The zero-based index where <paramref name='value'/> should be inserted.</param> /// <param name=' value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to insert.</param> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.Add'/> /// ------------------------------------------------------------------------------------ public void Insert(int index, XmlAssembly value) { if (List.Contains(value)) List.Remove(value); List.Insert(index, value); m_Hashtable[value.AssemblyName] = value; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Executes the Copy task. /// </summary> /// <exception cref="BuildException">A file that has to be copied does not exist or /// could not be copied.</exception> /// ------------------------------------------------------------------------------------ protected override void ExecuteTask() { if (SourceFile != null) { // Copy single file. base.ExecuteTask(); } else { // Copy file set contents. if (m_fResolveAssemblies) LoadReferences(); // get the complete path of the base directory of the fileset, ie, c:/work/nant/src m_dstBaseInfo = ToDirectory; XmlAssembly xmlAssembly; if (Append) xmlAssembly = m_Cache[Project.ProjectName]; else { xmlAssembly = new XmlAssembly(Project.ProjectName); m_Cache.Add(xmlAssembly); } // if source file is not specified use fileset foreach (string pathname in CopyFileSet.FileNames) { FileInfo srcInfo = new FileInfo(pathname); if (srcInfo.Exists || m_fForce) { // The full filepath to copy to. string dstFilePath = Path.Combine(m_dstBaseInfo.FullName, Path.GetFileName(srcInfo.FullName)); // do the outdated check FileInfo dstInfo = new FileInfo(dstFilePath); bool fOutdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime); if (Overwrite || fOutdated || m_fForce) { if (!IsInGAC(srcInfo)) { FileCopyMap[dstFilePath] = new FileDateInfo(srcInfo.FullName.ToLower(), srcInfo.LastWriteTime); if (dstInfo.Exists && dstInfo.Attributes != FileAttributes.Normal) File.SetAttributes( dstInfo.FullName, FileAttributes.Normal ); AddAssemblyAndRelatedFiles(xmlAssembly, srcInfo.FullName); } else Log(Level.Verbose, "Reference file {0} skipped", srcInfo.FullName); } else { if (!IsInGAC(srcInfo)) AddAssemblyAndRelatedFiles(xmlAssembly, srcInfo.FullName); } } else { if (FailOnError) { string msg = String.Format(CultureInfo.InvariantCulture, "Could not find file {0} to copy.", srcInfo.FullName); throw new BuildException(msg, Location); } else Log(Level.Error, "Reference file {0} does not exist", pathname); } } CreateDirectories(CopyFileSet.BaseDirectory); try { // do all the actual copy operations now... DoFileOperations(); } catch { if (FailOnError) throw; } finally { // save the references of this project in our settings file if (m_fResolveAssemblies) SaveReferences(); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Add the referenced assembly to the list of assemblies, resolve any referenced /// assemblies, and add the XML and PDB files. /// </summary> /// <param name="xmlAssembly">The assembly</param> /// <param name="referenceName">The name (and path) of the referenced assembly</param> /// ------------------------------------------------------------------------------------ private void AddAssemblyAndRelatedFiles(XmlAssembly xmlAssembly, string referenceName) { string srcFilePath; if (referenceName.StartsWith(ToDirectory.FullName)) srcFilePath = referenceName.Substring(ToDirectory.FullName.Length+1); else srcFilePath = referenceName; xmlAssembly.Add(srcFilePath); if (m_fResolveAssemblies) ResolveReferences(referenceName); AddFile(referenceName, "xml"); AddFile(referenceName, "pdb"); }
/// ------------------------------------------------------------------------------------ /// <summary> /// <para> /// Performs a single step in a recursive depth-first-search traversal /// of the target reference tree. /// </para> /// <para> /// The current target is first set to the "visiting" state, and pushed /// onto the "visiting" stack. /// </para> /// <para> /// An exception is then thrown if any child of the current node is in /// the visiting state, as that implies a circular dependency. The /// exception contains details of the cycle, using elements of the /// "visiting" stack. /// </para> /// <para> /// If any child has not already been "visited", this method is called /// recursively on it. /// </para> /// <para> /// The current target is set to the "visited" state. /// </para> /// </summary> /// <param name="assembly">The assembly to inspect.</param> /// <param name="states">A mapping from targets to states. The states in question are /// <see cref="State.Visiting"/> or <see cref="State.Visited"/>. Must not be /// <see langword="null"/>.</param> /// <param name="visiting">A stack of targets which are currently being visited. Must /// not be <see langword="null" />.</param> /// <returns><c>false</c> if circular reference was detected, otherwise <c>true</c>. /// </returns> /// <exception cref="BuildException">A circular dependency is detected.</exception> /// ------------------------------------------------------------------------------------ private bool CheckAssembly(XmlAssembly assembly, Hashtable states, Stack visiting) { if (assembly == null) { return(true); } string name = assembly.AssemblyName; ArrayList references = assembly.References; Log(Level.Debug, "Checking reference for {0}", name); states[name] = State.Visiting; visiting.Push(name); foreach (Reference reference in references) { object state = states[reference.Name]; if (state == null) { // not been visited if (Verbose) { Project.Indent(); } try { if (!CheckAssembly(m_Cache.Assemblies[reference.Name], states, visiting)) { return(false); } } finally { if (Verbose) { Project.Unindent(); } } } else if ((State)state == State.Visiting) { // Currently visiting this node, so have a cycle string msg = CreateCircularString(reference.Name, visiting); Log(Level.Info, msg); if (FailOnError) { throw new BuildException(msg); } return(false); } } string popName = (string)visiting.Pop(); if (name != popName) { string msg = string.Format("Unexpected internal error: expected to pop {0} but got {1}", name, popName); throw new Exception(msg); } states[name] = State.Visited; return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// <para> /// Performs a single step in a recursive depth-first-search traversal /// of the target reference tree. /// </para> /// <para> /// The current target is first set to the "visiting" state, and pushed /// onto the "visiting" stack. /// </para> /// <para> /// An exception is then thrown if any child of the current node is in /// the visiting state, as that implies a circular dependency. The /// exception contains details of the cycle, using elements of the /// "visiting" stack. /// </para> /// <para> /// If any child has not already been "visited", this method is called /// recursively on it. /// </para> /// <para> /// The current target is set to the "visited" state. /// </para> /// </summary> /// <param name="assembly">The assembly to inspect.</param> /// <param name="states">A mapping from targets to states. The states in question are /// <see cref="State.Visiting"/> or <see cref="State.Visited"/>. Must not be /// <see langword="null"/>.</param> /// <param name="visiting">A stack of targets which are currently being visited. Must /// not be <see langword="null" />.</param> /// <returns><c>false</c> if circular reference was detected, otherwise <c>true</c>. /// </returns> /// <exception cref="BuildException">A circular dependency is detected.</exception> /// ------------------------------------------------------------------------------------ private bool CheckAssembly(XmlAssembly assembly, Hashtable states, Stack visiting) { if (assembly == null) return true; string name = assembly.AssemblyName; ArrayList references = assembly.References; Log(Level.Debug, "Checking reference for {0}", name); states[name] = State.Visiting; visiting.Push(name); foreach (Reference reference in references) { object state = states[reference.Name]; if (state == null) { // not been visited if (Verbose) Project.Indent(); try { if (!CheckAssembly(m_Cache.Assemblies[reference.Name], states, visiting)) return false; } finally { if (Verbose) Project.Unindent(); } } else if ((State)state == State.Visiting) { // Currently visiting this node, so have a cycle string msg = CreateCircularString(reference.Name, visiting); Log(Level.Info, msg); if (FailOnError) throw new BuildException(msg); return false; } } string popName = (string)visiting.Pop(); if (name != popName) { string msg = string.Format("Unexpected internal error: expected to pop {0} but got {1}", name, popName); throw new Exception(msg); } states[name] = State.Visited; return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets a value indicating whether the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> contains the specified <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/>. /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to locate.</param> /// <returns> /// <c>true</c> if the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> is contained in the collection; /// otherwise, <c>false</c>. /// </returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.IndexOf'/> /// ------------------------------------------------------------------------------------ public bool Contains(XmlAssembly value) { return(List.Contains(value)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Returns the index of a <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> in /// the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> . /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to locate.</param> /// <returns> /// The index of the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> of <paramref name='value'/> in the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/>, if found; otherwise, -1. /// </returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.Contains'/> /// ------------------------------------------------------------------------------------ public int IndexOf(XmlAssembly value) { return(List.IndexOf(value)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Executes the Copy task. /// </summary> /// <exception cref="BuildException">A file that has to be copied does not exist or /// could not be copied.</exception> /// ------------------------------------------------------------------------------------ protected override void ExecuteTask() { if (SourceFile != null) { // Copy single file. base.ExecuteTask(); } else { // Copy file set contents. if (m_fResolveAssemblies) { LoadReferences(); } // get the complete path of the base directory of the fileset, ie, c:/work/nant/src m_dstBaseInfo = ToDirectory; XmlAssembly xmlAssembly; if (Append) { xmlAssembly = m_cache[Project.ProjectName]; } else { xmlAssembly = new XmlAssembly(Project.ProjectName); m_cache.Add(xmlAssembly); } // if source file is not specified use fileset foreach (var pathname in CopyFileSet.FileNames) { var srcInfo = new FileInfo(pathname); Log(Level.Debug, "Checking file {0}", pathname); if (srcInfo.Exists || m_force) { // The full filepath to copy to. var dstFilePath = Path.Combine(m_dstBaseInfo.FullName, Path.GetFileName(srcInfo.FullName)); // do the outdated check var dstInfo = new FileInfo(dstFilePath); Log(Level.Debug, "Comparing with destination file {0}", dstFilePath); var fOutdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime); if (Overwrite || fOutdated || m_force) { Log(Level.Debug, "Need to process: {0}", Overwrite ? "Overwrite is true" : fOutdated ? "src is newer than dst" : "force is true"); if (!IsInGAC(srcInfo)) { FileCopyMap[dstFilePath] = new FileDateInfo(IsUnix ? srcInfo.FullName : srcInfo.FullName.ToLower(), srcInfo.LastWriteTime); if (dstInfo.Exists && dstInfo.Attributes != FileAttributes.Normal) { File.SetAttributes(dstInfo.FullName, FileAttributes.Normal); } AddAssemblyAndRelatedFiles(xmlAssembly, srcInfo.FullName); } else { Log(Level.Verbose, "Reference file {0} skipped", srcInfo.FullName); } } else { if (!IsInGAC(srcInfo)) { AddAssemblyAndRelatedFiles(xmlAssembly, srcInfo.FullName); } } } else { if (FailOnError) { var msg = String.Format(CultureInfo.InvariantCulture, "Could not find file {0} to copy.", srcInfo.FullName); throw new BuildException(msg, Location); } Log(Level.Error, "Reference file {0} does not exist (ignored)", pathname); } } CreateDirectories(CopyFileSet.BaseDirectory); try { // do all the actual copy operations now... DoFileOperations(); } catch { if (FailOnError) { throw; } } finally { // save the references of this project in our settings file if (m_fResolveAssemblies) { SaveReferences(); } } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Copies the elements of an array to the end of the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/>. /// </summary> /// <param name='value'> /// An array of type <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> containing the objects to add to the collection. /// </param> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.Add'/> /// ------------------------------------------------------------------------------------ public void AddRange(XmlAssembly[] value) { for (int i = 0; (i < value.Length); i = (i + 1)) { this.Add(value[i]); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets a value indicating whether the /// <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> contains the specified <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/>. /// </summary> /// <param name='value'>The <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> to locate.</param> /// <returns> /// <c>true</c> if the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssembly'/> is contained in the collection; /// otherwise, <c>false</c>. /// </returns> /// <seealso cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection.IndexOf'/> /// ------------------------------------------------------------------------------------ public bool Contains(XmlAssembly value) { return List.Contains(value); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Copies the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> values to a one-dimensional <see cref='System.Array'/> instance at the /// specified index. /// </summary> /// <param name='array'>The one-dimensional <see cref='System.Array'/> that is the destination of the values copied from <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> .</param> /// <param name='index'>The index in <paramref name='array'/> where copying begins.</param> /// <exception cref='System.ArgumentException'><para><paramref name='array'/> is multidimensional.</para> <para>-or-</para> <para>The number of elements in the <see cref='SIL.FieldWorks.Build.Tasks.XmlAssemblyCollection'/> is greater than the available space between <paramref name='arrayIndex'/> and the end of <paramref name='array'/>.</para></exception> /// <exception cref='System.ArgumentNullException'><paramref name='array'/> is <see langword='null'/>. </exception> /// <exception cref='System.ArgumentOutOfRangeException'><paramref name='arrayIndex'/> is less than <paramref name='array'/>'s lowbound. </exception> /// <seealso cref='System.Array'/> /// ------------------------------------------------------------------------------------ public void CopyTo(XmlAssembly[] array, int index) { List.CopyTo(array, index); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Add an assembly /// </summary> /// <param name="assembly">The assembly</param> /// ------------------------------------------------------------------------------------ public void Add(XmlAssembly assembly) { m_assemblies[assembly.AssemblyName] = assembly; }