We use some Gradle base scripts on an central point. This scripts are included with "apply from:" from a large count of scripts. This base scripts need access to files relative to the script. How can I find the location of the base scripts?
Sample for one build.gradle:
apply from: "../../gradlebase/base1.gradle"
Sample for base1.gradle
println getScriptLocation()
I'm not sure if this is considered an internal interface, but DefaultScriptHandler has a getSourceFile() method, and the current instance is accessible via the buildscript property, so you can just use buildscript.sourceFile. It's a File instance pointing at the current script
I'm still not sure if I understood the question well but You can find path of current gradle script using following piece of code:
println project.buildscript.sourceFile
It gives the full path of the script that is currently running. Is that what You're looking for?
I'm pulling it off the stack.
buildscript {
def root = file('.').toString();
// We have to seek through, since groovy/gradle introduces
// a lot of abstraction that we see in the trace as extra frames.
// Fortunately, the first frame in the build dir is always going
// to be this script.
buildscript.metaClass.__script__ = file(
Thread.currentThread().stackTrace.find { ste ->
ste.fileName?.startsWith root
}.fileName
)
// later, still in buildscript
def libDir = "${buildscript.__script__.parent}/lib"
classpath files("${libDir}/custom-plugin.jar")
}
// This is important to do if you intend to use this path outside of
// buildscript{}, since everything else is pretty asynchronous, and
// they all share the buildscript object.
def __buildscripts__ = buildscript.__script__.parent;
Compact version for those who don't like clutter:
String r = file('.').toString();
buildscript.metaClass.__script__ = file(Thread.currentThread().stackTrace*.fileName?.find { it.startsWith r })
Another solution is set a property for the location of A.gradle in your global gradle settings at: {userhome}/.gradle/gradle.properties
My current workaround is to inject the path from the calling script. This is ugly hack.
The caller script must know where the base script is located. I save this path in a property before calling:
ext.scriptPath = '../../gradlebase'
apply from: "${scriptPath}/base1.gradle"
In base1.gradle I can also access the property ${scriptPath}
You could search for this scripts in the relative path like:
if(new File(rootDir,'../path/A.gradle').exists ()){
apply from: '../path/A.gradle'
}
This solution has not been tested with 'apply from', but has been tested with settings.gradle
Gradle has a Script.file(String path) function. I solved my problem by doing
def outDir = file("out")
def releaseDir = new File(outDir, "release")
And the 'out' directory is always next to the build.gradle in which this line is called.
Related
I have some code to create a Custom page object as part of a data import:
instance = PerformancePage(
run=run,
date=json_data['date'],
time=json_data['time'],
price=json_data['price'],
title=f'{run.title} {json_data["date"]} {json_data["id"]}',
content_type=ContentType.objects.get_for_model(PerformancePage)
)
perf = run.add_child(instance=instance)
and that sometimes raises:
django.core.exceptions.ValidationError: {'path': ['Page with this Path already exists.']}
A bit of debug code does show that there is another page out there with the same path:
except ValidationError:
print('error attempting to save', instance)
print('path', instance.path)
print('is leaf', run.is_leaf())
rivals = Page.objects.filter(path=instance.path)
print(rivals.last().specific.run == run)
Why might that be?
trying to manually increment the rival path to set a new path doesn't work either:
instance.path = rivals.last().specific._inc_path()
perf = run.add_child(instance=instance)
# still raises
Interestingly, if I just skip over those exceptions and continue my import,
when I print out those paths, they seem to follow a similar pattern:
path 00010001000T0005000D0001
path 00010001000T000800050001
path 00010001000T000900060001
path 00010001000T000A00050001
path 00010001000T000A00050001
path 00010001000T000A00070001
path 00010001000T000A00070001
path 00010001000T000A00030001
could that be relevant?
Looks like the in-memory parent "run" object was out of date. re-fetching it from the database before trying to add the child fixes the problem:
run = RunPage.objects.get(id=run.id)
I'm trying to generate combined JavaScript and CSS resources into a single file using gulp-concat using something like this:
var concatjs = gulp
.src(['app/js/app.js','app/js/*Controller.js', 'app/js/*Service.js'])
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
I get a concatted file with this, but the order of the javascript files embedded in the combined output file is random - in this case the controllers are showing up before the initial app.js file, which causes problems when trying to load the Angular app that expects app.js before any of the related resources are loaded. Likewise for CSS resources that get combined end up in random order, and again the order is somewhat important - ie. bootstrap needs to load before the theme and any custom style sheets.
How can I set up the concatenation process so that the order remains intact?
Update
So it turns out the ordering above DOES actually work by explicitly specifying the file order in the array of file specs. So in this case the crucial thing is to list app/js/app.js first, then let the rest of the scripts where order doesn't matter in in any order.
The reason I failed to see this behavior (Duh!) is that Gulp Watch was running and the gulpfile.js update wasn't actually reflected in the output. Restarting gulp did update the script. Neophyte error...
Other Thoughts:
Still wondering though - is this the right place to specify build order? It seems you're now stuffing application logic (load order) into the build script, which doesn't feel right. Are there other approaches to address this?
For an angular application like the one in your example (and it's dependency management), I normally use this kind of syntax: gulp.src(['app\js\app.js', 'app\js\**\*.js']).
You can also use just gulp.src('app\js\**\*.js') if your app.js file is the first one in alphabetic order.
I see your point about moving the load file order into the build script: I had the same feeling till I started using gulp-inject for injecting the unminified files references in my index.html at development time and injecting the bundled, minified and versioned ones in the production index file. Using that glob ordering solution across all my development cycle made so sense to me that i don't think to it anymore.
Finally, a possible solution for this 'ordering smell' can be using browserify but to me it is just complicating the architecture for an angular application: in the end, as you said, you just need that one specific file is called before all the other ones.
For my js i use a particular structure/naming convention which helps. I split it up into directories by feature, where each 'feature' is then treated as a separate encapsulated module.
So for my projects i have,
app/js/
- app.js
- app.routes.js
- app.config.js
/core/
- core.js
- core.controllers.js
- core.services.js
/test/
- .spec.js test files for module here
/feature1/
- feature1.js
- feature1.controllers.js
/feature2/
- feature2.js
- feature2.controllers.js
...
So each directory has a file of the same name that simply has the initial module definition in it, which is all that app.js has in it for the whole app. So for feature1.js
angular.module('feature1', [])
and then subsequent files in the module retrieve the module and add things (controllers/services/factories etc) to it.
angular.module('feature1')
.controller(....)
Anyway, i'll get to the point...
As i have a predefined structure and know that a specific file has to go first for each module, i'm able to use the function below to sort everything into order before it gets processed by gulp.
This function depends on npm install file and npm install path
function getModules(src, app, ignore) {
var modules = [];
file.walkSync(src, function(dirPath, dirs, files) {
if(files.length < 1)
return;
var dir = path.basename(dirPath)
module;
if(ignore.indexOf(dir) === -1) {
module = dirPath === src ? app : dir;
files = files.sort(function(a, b) {
return path.basename(a, '.js') === module ? -1 : 1;
})
.filter(function(value) {
return value.indexOf('.') !== 0;
})
.map(function(value) {
return path.join(dirPath, value);
})
modules = modules.concat(files);
}
})
return modules;
}
It walks the directory structure passed to it, takes the files from each directory (or module) and sorts them into the correct order, ensuring that the module definition file is always first. It also ignores any directories that appear in the 'ignore' array and removes any hidden files that begin with '.'
Usage would be,
getModules(src, appName, ignoreDirs);
src is the dir you want to recurse from
appName is the name of your app.js file - so 'app'
ignoreDirs is an array of directory names you'd like to ignore
so
getModules('app/js', 'app', ['test']);
And it returns an array of all the files in your app in the correct order, which you could then use like:
gulp.task('scripts', function() {
var modules = getModules('app/js', 'app', ['test']);
return gulp.src(modules)
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
});
I'm using the CakePHP Plugin AssetCompress (v 0.7) which works fine, except that it doesn't cache any files in the directory. This is my asset_compress.ini setup:
[General]
writeCache = true
cacheConfig = false
alwaysEnableController = true
debug = false
[js]
timestamp = true
paths[] = WEBROOT/js/
cachePath = WEBROOT/cache_js/
[speedtest.min.js]
files[] = speedtest/speedtest.js
Additional notes:
I set debug to "0" in core.php
the cache_js folder is writeable (777)
also I'm using MemCache as a caching engine (not sure if this might cause the issue)
Has anybody experienced the same issue with the Asset Compress plugin?
Update: This is what I use for the CSS/Less part, works pretty well: https://github.com/Hyra/less
If I understand well this Github's wiki page you should change cacheConfig = false to cacheConfig = true to take advantage of MemCache.
You have to generate the files using the shell script. The files are not automatically generated.
https://github.com/markstory/asset_compress/wiki/Shell
To generate and store static assets defined in the asset_compress.ini config or through the AssetCompress helper on the fly. This is to save you having to manually run the console script everytime you change you css or js files.
This is what some will define as a "nasty" hack, I call it a working solution. It simply runs the console script via the php exec() method every time the AppController beforeFilter() runs and the debug level is greater than 0. So in production where your debug level should be 0, the exec() won't be run.
Add the following to your /app/Controller/AppController.php beforeFilter() function.
if(Configure::read('debug') > 0){
exec(APP.'Console'.DS.'cake -app '.APP.' AssetCompress.asset_compress build -f');
}
This is assuming that you can run the normal AssetCompress from the console (linux) or cmd prompt (windows)
Is there a way to reference the database.sqlite file without knowing the absolute path?
_db = QSqlDatabase::addDatabase("QSQLITE");
_db.setDatabaseName("/the/path/i/dont/know/database.sqlite");
I already tried to add the database.sqlite to the Resources folder and call it via qrc:, but apparently it is not possible to write to a resource file.
I also tried using QApplication::applicationDirPath();, but this would result in different paths depending on the user's OS. E.g. it appends MyApp.app/Contents/MacOS to the actual directory.
When you create a QSqlDatabase with SQLite as a backend you have two options:
Give an absolute path as a db name
Give a relative path: in this case the database will be saved in the directory of your binary.
So you must know absolute path of your db in your case.
edit
In the case you initially know where the database should be located you can either hardcode it (which is never wise) or you can create a configuration and load it using QSettings. For example:
QSettings settings;
QString dbPath = settings.readValue("DBPath", QString(/*fallback path*/)).toString();
//do smth with dbPath
Take a look further here
if you want to store the db per user you shout use this:
QDesktopServices::storageLocation(QDesktopServices::DataLocation)
this method returns the location where persistent application data can be stored.
for more information check this: http://doc.trolltech.com/4.5/qdesktopservices.html#storageLocation
I have developed a grails app which has user file uploads (docs, etc..), they are stored in the relative folder "web-app/upload".
My question is that I do not know what is the best way to perform automatically war deployments and keep this folder. Because when I redeploy in Tomcat the whole app folder is deleted and all the files are deleted.
Additionaly I need a generic configuration fron set an external location from this Files
Have you found a solution for that?
P.D.: If I use System.properties['base.dir'] the result is null, and if I use a ApplicationHolder.application.mainContext.getResource() it return a temp path. :(
You should not be uploading files into your WAR structure. You should upload them to some external location.
I was able to solve partial as follow
//for development environment
def root = System.properties['base.dir']?.toString()
if(!root){
//for production environment in war deplements
def tmpRoot = ApplicationHolder.application.mainContext.getResource('WEB-INF').getFile().toString()
root = tmpRoot.substring(0, tmpRoot.indexOf(File.separator + 'temp' + File.separator))
}
if(!root){
throw new Exception('Not found a valid path')
}
return root + File.separator
I hope it can be useful to others
Regards,
Yecid PacĂfico
This code obtains the parent folder where the application is located:
String path = servletContext.getRealPath("/");
String parentStr = new File(path).getParentFile().getParent();
I mean, if the web application were located in D:\somefolder\myWeb
path would be D:\somefolder\myWeb\web-app
parentStr would be D:\somefolder
So you could save the files in D:\somefolder\files-outside-myWeb-context
Is it what you are looking for?