diff --git a/source/dub/commandline.d b/source/dub/commandline.d index d553d8b..0a54fc6 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -751,7 +751,7 @@ this.argumentsPattern = "[]"; this.description = "Removes intermediate build files and cached build results"; this.helpText = [ - "This command removes any cached build files of the given package(s). The final target file, as well as any copyFiles are currently not removed.", + "This command removes any cached build files of the given package(s). The final target file, as well as any copyFiles and copyDirs are currently not removed.", "Without arguments, the package in the current working directory will be cleaned." ]; } diff --git a/source/dub/compilers/buildsettings.d b/source/dub/compilers/buildsettings.d index f64362f..8abb3db 100644 --- a/source/dub/compilers/buildsettings.d +++ b/source/dub/compilers/buildsettings.d @@ -27,6 +27,7 @@ string[] libs; string[] sourceFiles; string[] copyFiles; + string[] copyDirs; string[] versions; string[] debugVersions; string[] importPaths; @@ -62,6 +63,7 @@ addLibs(bs.libs); addSourceFiles(bs.sourceFiles); addCopyFiles(bs.copyFiles); + addCopyDirs(bs.copyDirs); addVersions(bs.versions); addDebugVersions(bs.debugVersions); addImportPaths(bs.importPaths); @@ -82,6 +84,7 @@ void prependSourceFiles(in string[] value...) { prepend(sourceFiles, value); } void removeSourceFiles(in string[] value...) { removePaths(sourceFiles, value); } void addCopyFiles(in string[] value...) { add(copyFiles, value); } + void addCopyDirs(in string[] value...) { add(copyDirs, value); } void addVersions(in string[] value...) { add(versions, value); } void addDebugVersions(in string[] value...) { add(debugVersions, value); } void addImportPaths(in string[] value...) { add(importPaths, value); } @@ -171,10 +174,11 @@ importPaths = 1<<7, stringImportPaths = 1<<8, options = 1<<9, + copyDirs = 1<<10, none = 0, - commandLine = dflags|copyFiles, + commandLine = dflags|copyFiles|copyDirs, commandLineSeparate = commandLine|lflags, - all = dflags|lflags|libs|sourceFiles|copyFiles|versions|debugVersions|importPaths|stringImportPaths|options, + all = dflags|lflags|libs|sourceFiles|copyFiles|copyDirs|versions|debugVersions|importPaths|stringImportPaths|options, noOptions = all & ~options } diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 9f5e65d..e7e7f42 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -136,6 +136,7 @@ assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); + assert(fields & BuildSetting.copyDirs); } void extractBuildOptions(ref BuildSettings settings) const diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index e31053f..46fbd7b 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -135,6 +135,7 @@ assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); + assert(fields & BuildSetting.copyDirs); } void extractBuildOptions(ref BuildSettings settings) const diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index f75caa8..0963394 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -125,6 +125,7 @@ assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); + assert(fields & BuildSetting.copyDirs); } void extractBuildOptions(ref BuildSettings settings) const diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index e7b057a..1b74557 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -216,6 +216,8 @@ m_temporaryFiles ~= exe_file_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; + foreach (f; buildsettings.copyDirs) + m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; } } @@ -266,6 +268,8 @@ m_temporaryFiles ~= exe_file_path; foreach (f; buildsettings.copyFiles) m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; + foreach (f; buildsettings.copyDirs) + m_temporaryFiles ~= Path(buildsettings.targetPath).parentPath ~ Path(f).head; } } diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 533a1c4..39f6522 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -376,6 +376,71 @@ } } } + + if (buildsettings.copyDirs.length) { + + void copyFolderRec(Path folder, Path dstfolder) + { + mkdirRecurse(dstfolder.toNativeString()); + foreach (de; iterateDirectory(folder.toNativeString())) { + if (de.name.startsWith(".")) continue; + if (de.isDirectory) { + copyFolderRec(folder ~ de.name, dstfolder ~ de.name); + } else { + try copyFile(folder ~ de.name, dstfolder ~ de.name, true); + catch (Exception e) { + logWarn("Failed to copy file %s: %s", (folder ~ de.name).toNativeString(), e.msg); + } + } + } + } + + void tryCopyDir(string file) + { + auto src = Path(file); + if (!src.absolute) src = pack_path ~ src; + auto dst = target_path ~ Path(file).head; + if (src == dst) { + logDiagnostic("Skipping copy of %s (same source and destination)", file); + return; + } + logDiagnostic(" %s to %s", src.toNativeString(), dst.toNativeString()); + try { + // TODO: copy directory + copyFolderRec(src, dst); + } catch(Exception e) logWarn("Failed to copy %s to %s: %s", src.toNativeString(), dst.toNativeString(), e.msg); + } + + logInfo("Copying dirs for %s...", pack); + string[] globs; + foreach (f; buildsettings.copyDirs) + { + if (f.canFind("*", "?") || + (f.canFind("{") && f.balancedParens('{', '}')) || + (f.canFind("[") && f.balancedParens('[', ']'))) + { + globs ~= f; + } + else + { + tryCopyDir(f); + } + } + if (globs.length) // Search all files for glob matches + { + foreach (f; dirEntries(pack_path.toNativeString(), SpanMode.breadth)) + { + foreach (glob; globs) + { + if (f.globMatch(glob)) + { + tryCopyDir(f); + break; + } + } + } + } + } } } diff --git a/source/dub/project.d b/source/dub/project.d index ee2cc78..378b3dd 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -733,6 +733,7 @@ dst.addImportFiles(processVars(project, pack, settings.importFiles, true)); dst.addStringImportFiles(processVars(project, pack, settings.stringImportFiles, true)); dst.addCopyFiles(processVars(project, pack, settings.copyFiles, true)); + dst.addCopyDirs(processVars(project, pack, settings.copyDirs, true)); dst.addVersions(processVars(project, pack, settings.versions)); dst.addDebugVersions(processVars(project, pack, settings.debugVersions)); dst.addImportPaths(processVars(project, pack, settings.importPaths, true)); diff --git a/source/dub/recipe/json.d b/source/dub/recipe/json.d index 1e5e013..d686d7e 100644 --- a/source/dub/recipe/json.d +++ b/source/dub/recipe/json.d @@ -210,6 +210,7 @@ case "sourcePath": bs.sourcePaths[suffix] ~= [value.get!string()]; break; // deprecated case "excludedSourceFiles": bs.excludedSourceFiles[suffix] = deserializeJson!(string[])(value); break; case "copyFiles": bs.copyFiles[suffix] = deserializeJson!(string[])(value); break; + case "copyDirs": bs.copyDirs[suffix] = deserializeJson!(string[])(value); break; case "versions": bs.versions[suffix] = deserializeJson!(string[])(value); break; case "debugVersions": bs.debugVersions[suffix] = deserializeJson!(string[])(value); break; case "importPaths": bs.importPaths[suffix] = deserializeJson!(string[])(value); break; @@ -256,6 +257,7 @@ foreach (suffix, arr; bs.sourcePaths) ret["sourcePaths"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.excludedSourceFiles) ret["excludedSourceFiles"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.copyFiles) ret["copyFiles"~suffix] = serializeToJson(arr); + foreach (suffix, arr; bs.copyDirs) ret["copyDirs"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.versions) ret["versions"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.debugVersions) ret["debugVersions"~suffix] = serializeToJson(arr); foreach (suffix, arr; bs.importPaths) ret["importPaths"~suffix] = serializeToJson(arr); diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index dad1220..ccf82b2 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -146,6 +146,7 @@ string[][string] sourcePaths; string[][string] excludedSourceFiles; string[][string] copyFiles; + string[][string] copyDirs; string[][string] versions; string[][string] debugVersions; string[][string] importPaths; @@ -209,6 +210,7 @@ getPlatformSetting!("sourceFiles", "addSourceFiles")(dst, platform); getPlatformSetting!("excludedSourceFiles", "removeSourceFiles")(dst, platform); getPlatformSetting!("copyFiles", "addCopyFiles")(dst, platform); + getPlatformSetting!("copyDirs", "addCopyDirs")(dst, platform); getPlatformSetting!("versions", "addVersions")(dst, platform); getPlatformSetting!("debugVersions", "addDebugVersions")(dst, platform); getPlatformSetting!("importPaths", "addImportPaths")(dst, platform);