/// <summary> /// Inserts a file into the SPC archive. If a file with the same name already exists within the archive, it will be replaced. /// </summary> /// <param name="filename">The path of the file to be inserted into the SPC archive.</param> /// <param name="compress">Whether the subfile should be compressed before inserting. Unless you know what you're doing, leave this set to "true".</param> /// <param name="confirmation">A delegate whose output will determine whether a file will be replaced. If null, there is no confirmation.</param> public void InsertSubfile(string filename, bool compress = true, OverwriteConfirmation confirmation = null) { FileInfo info = new FileInfo(filename); if (!info.Exists) { Console.WriteLine($"ERROR: Target file\"{info.FullName}\" does not exist."); return; } // Check if a subfile already exists with the specified name int existingIndex = -1; for (int s = 0; s < Subfiles.Count; ++s) { if (info.Name == Subfiles[s].Name) { if (confirmation == null || confirmation()) { existingIndex = s; break; } } } using BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open)); int subfileSize = (int)reader.BaseStream.Length; SpcSubfile subfileToInject = new SpcSubfile { CompressionFlag = 1, UnknownFlag = (short)(subfileSize > ushort.MaxValue ? 8 : 4), // seems like this flag might relate to size? This is a BIG guess though. CurrentSize = subfileSize, OriginalSize = subfileSize, Name = info.Name, Data = reader.ReadBytes(subfileSize) }; reader.Close(); if (compress) { subfileToInject.Compress(); } // Check if a subfile already exists with the specified name and replace if (existingIndex != -1) { Subfiles[existingIndex] = subfileToInject; return; } // We should only reach this code if there is not an existing subfile with the same name Subfiles.Add(subfileToInject); }
/// <summary> /// Copies the dependencies from the repository to the specified directory. /// The destination directory is checked for an existing version of the /// dependency before copying. The OverwriteConfirmation delegate is /// called for the first existing file or directory. If the delegate /// returns true, the old dependency is deleted and the new one copied. /// </summary> /// <param name="dependencies">The dependencies to copy.</param> /// <param name="destDirectory">Destination directory.</param> /// <param name="confirmer">Confirmer - the delegate for confirming overwriting.</param> public void CopyDependencies( Dictionary <string, Dependency> dependencies, string destDirectory, OverwriteConfirmation confirmer) { if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } foreach (Dependency dep in dependencies.Values) { // match artifact-*. The - is important to distinguish art-1.0.0 // from artifact-1.0.0 (or base and basement). string[] dups = Directory.GetFiles(destDirectory, dep.Artifact + "-*"); bool doCopy = true; bool doCleanup = false; foreach (string s in dups) { // skip the .meta files (a little Unity creeps in). if (s.EndsWith(".meta")) { continue; } string existing = Path.GetFileNameWithoutExtension(s); string artifactName = null; string artifactVersion = null; int idx = existing.Length; // handle artifacts like android-support-4.0.0-alpha.aar while (artifactVersion == null && idx > 0) { // the version is after the last - idx = existing.LastIndexOf("-", idx); if (idx > 0) { artifactName = existing.Substring(0, idx); artifactVersion = existing.Substring(idx + 1); if (!char.IsDigit(artifactVersion.ToCharArray()[0])) { idx--; artifactVersion = null; } } } Dependency oldDep = new Dependency(dep.Group, artifactName, artifactVersion); // add the artifact version so BestVersion == version. oldDep.AddVersion(oldDep.Version); doCleanup = doCleanup || confirmer == null || confirmer(oldDep, dep); if (doCleanup) { if (File.Exists(s)) { File.Delete(s); } else if (Directory.Exists(s)) { Directory.Delete(s); } } else { doCopy = false; } } if (doCopy) { string aarFile = null; // TODO(wilkinsonclay): get the extension from the pom file. string[] packaging = { ".aar", ".jar" }; string baseName = null; foreach (string ext in packaging) { string fname = Path.Combine(dep.BestVersionPath, dep.Artifact + "-" + dep.BestVersion + ext); if (File.Exists(fname)) { baseName = dep.Artifact + "-" + dep.BestVersion + ext; aarFile = fname; } } if (aarFile != null) { string destName = Path.Combine(destDirectory, baseName); if (File.Exists(destName)) { File.Delete(destName); } File.Copy(aarFile, destName); } else { throw new ResolutionException("Cannot find artifact for " + dep); } } } }
/// <summary> /// Copies the dependencies from the repository to the specified directory. /// The destination directory is checked for an existing version of the /// dependency before copying. The OverwriteConfirmation delegate is /// called for the first existing file or directory. If the delegate /// returns true, the old dependency is deleted and the new one copied. /// </summary> /// <param name="dependencies">The dependencies to copy.</param> /// <param name="destDirectory">Destination directory.</param> /// <param name="confirmer">Confirmer - the delegate for confirming overwriting.</param> public void CopyDependencies( Dictionary <string, Dependency> dependencies, string destDirectory, OverwriteConfirmation confirmer) { if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } foreach (Dependency dep in dependencies.Values) { // match artifact-*. The - is important to distinguish art-1.0.0 // from artifact-1.0.0 (or base and basement). string[] dups = Directory.GetFileSystemEntries(destDirectory, dep.Artifact + "-*"); bool doCopy = true; bool doCleanup = false; foreach (string s in dups) { // skip the .meta files (a little Unity creeps in). if (s.EndsWith(".meta")) { continue; } // Strip the package extension from filenames. Directories generated from // unpacked AARs do not have extensions. string existing = Directory.Exists(s) ? s : Path.GetFileNameWithoutExtension(s); // Extract the version from the filename. // dep.Artifact is the name of the package (prefix) // The regular expression extracts the version number from the filename // handling filenames like foo-1.2.3-alpha. System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match( existing.Substring(dep.Artifact.Length + 1), "^([0-9.]+)"); if (!match.Success) { continue; } string artifactVersion = match.Groups[1].Value; Dependency oldDep = new Dependency(dep.Group, dep.Artifact, artifactVersion, packageIds: dep.PackageIds, repositories: dep.Repositories); // add the artifact version so BestVersion == version. oldDep.AddVersion(oldDep.Version); // If the existing artifact matches the new dependency, don't modify it. if (dep.Key == oldDep.Key) { continue; } doCleanup = doCleanup || confirmer == null || confirmer(oldDep, dep); if (doCleanup) { DeleteExistingFileOrDirectory(s); } else { doCopy = false; } } if (doCopy) { string aarFile = null; // TODO(wilkinsonclay): get the extension from the pom file. string baseName = null; string extension = null; foreach (string ext in Packaging) { string fname = Path.Combine(dep.BestVersionPath, dep.Artifact + "-" + dep.BestVersion + ext); if (File.Exists(fname)) { baseName = dep.Artifact + "-" + dep.BestVersion; aarFile = fname; extension = ext; } } if (aarFile != null) { string destName = Path.Combine(destDirectory, baseName) + (extension == ".srcaar" ? ".aar" : extension); string destNameUnpacked = Path.Combine( destDirectory, Path.GetFileNameWithoutExtension(destName)); string existingName = File.Exists(destName) ? destName : Directory.Exists(destNameUnpacked) ? destNameUnpacked : null; if (existingName != null) { doCopy = File.GetLastWriteTime(existingName).CompareTo( File.GetLastWriteTime(aarFile)) < 0; if (doCopy) { DeleteExistingFileOrDirectory(existingName); } } if (doCopy) { File.Copy(aarFile, destName); } } else { throw new ResolutionException("Cannot find artifact for " + dep); } } } }
/// <summary> /// Copies the dependencies from the repository to the specified directory. /// The destination directory is checked for an existing version of the /// dependency before copying. The OverwriteConfirmation delegate is /// called for the first existing file or directory. If the delegate /// returns true, the old dependency is deleted and the new one copied. /// </summary> /// <param name="dependencies">The dependencies to copy.</param> /// <param name="destDirectory">Destination directory.</param> /// <param name="confirmer">Confirmer - the delegate for confirming overwriting.</param> public void CopyDependencies( Dictionary <string, Dependency> dependencies, string destDirectory, OverwriteConfirmation confirmer) { if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } // Build a dictionary of the source dependencies without the version in the key // to simplify looking up dependencies currently in the project based upon filenames. var currentDepsByVersionlessKey = new Dictionary <string, KeyValuePair <Dependency, string> >(); foreach (var item in GetCurrentDependencies(dependencies, destDirectory, repoPaths: repositoryPaths)) { currentDepsByVersionlessKey[item.Value.Key.VersionlessKey] = item.Value; } foreach (var dep in dependencies.Values) { KeyValuePair <Dependency, string> oldDepFilenamePair; if (currentDepsByVersionlessKey.TryGetValue(dep.VersionlessKey, out oldDepFilenamePair)) { if (oldDepFilenamePair.Key.BestVersion != dep.BestVersion && (confirmer == null || confirmer(oldDepFilenamePair.Key, dep))) { DeleteExistingFileOrDirectory(oldDepFilenamePair.Value, includeMetaFiles: true); } else { continue; } } string aarFile = dep.BestVersionArtifact; if (aarFile != null) { string baseName = Path.GetFileNameWithoutExtension(aarFile); string extension = Path.GetExtension(aarFile); string destName = Path.Combine(destDirectory, baseName) + (extension == ".srcaar" ? ".aar" : extension); string destNameUnpacked = Path.Combine( destDirectory, Path.GetFileNameWithoutExtension(destName)); string existingName = File.Exists(destName) ? destName : Directory.Exists(destNameUnpacked) ? destNameUnpacked : null; bool doCopy = true; if (existingName != null) { doCopy = File.GetLastWriteTime(existingName).CompareTo( File.GetLastWriteTime(aarFile)) < 0; if (doCopy) { DeleteExistingFileOrDirectory(existingName, includeMetaFiles: true); } } if (doCopy) { File.Copy(aarFile, destName); } } else { throw new ResolutionException("Cannot find artifact for " + dep); } } }
/// <summary> /// Copies the dependencies from the repository to the specified directory. /// The destination directory is checked for an existing version of the /// dependency before copying. The OverwriteConfirmation delegate is /// called for the first existing file or directory. If the delegate /// returns true, the old dependency is deleted and the new one copied. /// </summary> /// <param name="dependencies">The dependencies to copy.</param> /// <param name="destDirectory">Destination directory.</param> /// <param name="confirmer">Confirmer - the delegate for confirming overwriting.</param> public void CopyDependencies( Dictionary<string, Dependency> dependencies, string destDirectory, OverwriteConfirmation confirmer) { if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } foreach (Dependency dep in dependencies.Values) { // match artifact-*. The - is important to distinguish art-1.0.0 // from artifact-1.0.0 (or base and basement). string[] dups = Directory.GetFileSystemEntries(destDirectory, dep.Artifact + "-*"); bool doCopy = true; bool doCleanup = false; foreach (string s in dups) { // skip the .meta files (a little Unity creeps in). if (s.EndsWith(".meta")) { continue; } // Strip the package extension from filenames. Directories generated from // unpacked AARs do not have extensions. string existing = Directory.Exists(s) ? s : Path.GetFileNameWithoutExtension(s); // Extract the version from the filename. // dep.Artifact is the name of the package (prefix) // The regular expression extracts the version number from the filename // handling filenames like foo-1.2.3-alpha. string artifactName = existing.Substring(dep.Artifact.Length + 1); System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match(artifactName, "^([0-9.]+)"); if (!match.Success) continue; string artifactVersion = match.Groups[1].Value; Dependency oldDep = new Dependency(dep.Group, artifactName, artifactVersion, packageIds: dep.PackageIds, repositories: dep.Repositories); // add the artifact version so BestVersion == version. oldDep.AddVersion(oldDep.Version); // If the existing artifact matches the new dependency, don't modify it. if (dep.Key == oldDep.Key) continue; doCleanup = doCleanup || confirmer == null || confirmer(oldDep, dep); if (doCleanup) { DeleteExistingFileOrDirectory(s); } else { doCopy = false; } } if (doCopy) { string aarFile = null; // TODO(wilkinsonclay): get the extension from the pom file. string baseName = null; string extension = null; foreach (string ext in Packaging) { string fname = Path.Combine(dep.BestVersionPath, dep.Artifact + "-" + dep.BestVersion + ext); if (File.Exists(fname)) { baseName = dep.Artifact + "-" + dep.BestVersion; aarFile = fname; extension = ext; } } if (aarFile != null) { string destName = Path.Combine(destDirectory, baseName) + (extension == ".srcaar" ? ".aar" : extension); string destNameUnpacked = Path.Combine( destDirectory, Path.GetFileNameWithoutExtension(destName)); string existingName = File.Exists(destName) ? destName : Directory.Exists(destNameUnpacked) ? destNameUnpacked : null; if (existingName != null) { doCopy = File.GetLastWriteTime(existingName).CompareTo( File.GetLastWriteTime(aarFile)) < 0; if (doCopy) DeleteExistingFileOrDirectory(existingName); } if (doCopy) { File.Copy(aarFile, destName); } } else { throw new ResolutionException("Cannot find artifact for " + dep); } } } }