Newer
Older
dub_jkp / source / dub / packagesuppliers / filesystem.d
  1. module dub.packagesuppliers.filesystem;
  2.  
  3. import dub.packagesuppliers.packagesupplier;
  4.  
  5. /**
  6. File system based package supplier.
  7.  
  8. This package supplier searches a certain directory for files with names of
  9. the form "[package name]-[version].zip".
  10. */
  11. class FileSystemPackageSupplier : PackageSupplier {
  12. import dub.internal.logging;
  13.  
  14. version (Have_vibe_core) import dub.internal.vibecompat.inet.path : toNativeString;
  15. import std.exception : enforce;
  16. private {
  17. NativePath m_path;
  18. }
  19.  
  20. this(NativePath root) { m_path = root; }
  21.  
  22. override @property string description() { return "file repository at "~m_path.toNativeString(); }
  23.  
  24. Version[] getVersions(string package_id)
  25. {
  26. import std.algorithm.sorting : sort;
  27. import std.file : dirEntries, DirEntry, SpanMode;
  28. import std.conv : to;
  29. Version[] ret;
  30. foreach (DirEntry d; dirEntries(m_path.toNativeString(), package_id~"*", SpanMode.shallow)) {
  31. NativePath p = NativePath(d.name);
  32. logDebug("Entry: %s", p);
  33. enforce(to!string(p.head)[$-4..$] == ".zip");
  34. auto vers = p.head.name[package_id.length+1..$-4];
  35. logDebug("Version: %s", vers);
  36. ret ~= Version(vers);
  37. }
  38. ret.sort();
  39. return ret;
  40. }
  41.  
  42. void fetchPackage(NativePath path, string packageId, Dependency dep, bool pre_release)
  43. {
  44. import dub.internal.vibecompat.core.file : copyFile, existsFile;
  45. enforce(path.absolute);
  46. logInfo("Storing package '%s', version requirements: %s", packageId, dep);
  47. auto filename = bestPackageFile(packageId, dep, pre_release);
  48. enforce(existsFile(filename));
  49. copyFile(filename, path);
  50. }
  51.  
  52. Json fetchPackageRecipe(string packageId, Dependency dep, bool pre_release)
  53. {
  54. import std.array : split;
  55. import std.path : stripExtension;
  56. import std.algorithm : startsWith, endsWith;
  57. import dub.internal.utils : packageInfoFileFromZip;
  58. import dub.recipe.io : parsePackageRecipe;
  59. import dub.recipe.json : toJson;
  60.  
  61. auto filePath = bestPackageFile(packageId, dep, pre_release);
  62. string packageFileName;
  63. string packageFileContent = packageInfoFileFromZip(filePath, packageFileName);
  64. auto recipe = parsePackageRecipe(packageFileContent, packageFileName);
  65. Json json = toJson(recipe);
  66. auto basename = filePath.head.name;
  67. enforce(basename.endsWith(".zip"), "Malformed package filename: " ~ filePath.toNativeString);
  68. enforce(basename.startsWith(packageId), "Malformed package filename: " ~ filePath.toNativeString);
  69. json["version"] = basename[packageId.length + 1 .. $-4];
  70. return json;
  71. }
  72.  
  73. SearchResult[] searchPackages(string query)
  74. {
  75. // TODO!
  76. return null;
  77. }
  78.  
  79. private NativePath bestPackageFile(string packageId, Dependency dep, bool pre_release)
  80. {
  81. import std.algorithm.iteration : filter;
  82. import std.array : array;
  83. import std.format : format;
  84. NativePath toPath(Version ver) {
  85. return m_path ~ (packageId ~ "-" ~ ver.toString() ~ ".zip");
  86. }
  87. auto versions = getVersions(packageId).filter!(v => dep.matches(v)).array;
  88. enforce(versions.length > 0, format("No package %s found matching %s", packageId, dep));
  89. foreach_reverse (ver; versions) {
  90. if (pre_release || !ver.isPreRelease)
  91. return toPath(ver);
  92. }
  93. return toPath(versions[$-1]);
  94. }
  95. }