gradle properties file - after putting new property how to preserve comments? - groovy

Whenever i add a property to gradle.properties file the comments in the file get erased. I'd like to preserve all comments. A comment is defined as anything with a #
The task im using to update the gradle.properties file looks like this:
task updateSomeProperty << {
if(project.hasProperty('mynewProperty')) {
File gradleProperties = file("gradle.properties")
Properties props = new Properties()
props.load(new FileInputStream("gradle.properties"))
props.put("moldProperty",project.getProperty('mynewProperty'))
props.store(new FileWriter(gradleProperties),null);
println 'Updated old property to new property.'
}
}
and on the command line i run gradle updateSomeProperty -PmynewProperty=1234
everything works and the property gets injected into the file but the comments in the file get cleared. Notice how i am using null in props.store(new FileWriter(gradleProperties),null); i was thinking if i passed a null comment it would keep the comment but its not working. how do i do this ?
if i cant preserve the comments, is there a way to get all the comments and then i can put them back with the fileWriter command:
props.store(new FileWriter(gradleProperties),MY_COMMENTS);

Unfortunately, because you are using a plain java properties instance, according to Properties#store() method, comments parameter is a new comment, furthermore it is just the comment at the first linee of the newly saved properties file. If you want to store previews comments, you should try some other solution. For example, you have to provide your own implementation pf properies and use it to store a new property within exosting properties file. You can find some examp,es on internet, like one here. But sure, it doesn't seem to be straightforward for Gradle script.

Related

Using Groovy create Project properties in SoapUI

I have 50+ tests in my current SoapUI workspace. I need to add a new project level parameter on all of these tests. Is there a way I can do this using the groovy console within SoapUI?
For example :
testRunner.testCase.testSuite.project.setPropertyValue( "SuperMan",("SuperMan"));
I can run this to create a property within the current working project.
Is there a way I can create this under all projects on my current workspace?
Thanks in advance.
Yes, We can do this but it's little tricky.
Way to do this:
Create a empty generic project in soapui, Add empty testsuite, add Empty testcase
In test case Add a groovy script step
Now paste this groovy code
for(project in com.eviware.soapui.SoapUI.workspace.projectList) {
if(project.open && project.name != testRunner.testCase.testSuite.project.name){
project.setPropertyValue( "TestProperty","TestValue");
}
}
Run the groovy step, you will get property added at Project level.
Please mark this as correct response if this solve your problem.
Using your testRunner access you simply need one level more workspace. From here you can access projects map and iterate over each project adding the property:
testRunner.testCase.testSuite.project.workspace.projects.each{ key, proj ->
proj.setPropertyValue('superman','superman')
}
This code doesn't add the property on closed projects in workspace but not fails accessing it.
Alternatively as #Rao suggest on his comment it's possible to use default it object iterator and access the value instead of defining key, proj -> on each:
testRunner.testCase.testSuite.project.workspace.projects.each{
it.value.setPropertyValue('superman','superman')
}
I prefer the first approach for clarity.
Hope it helps,

How can ConfigSlurper's groovy file can call methods defined in build.gradle?

I am working on project whose build logic is defined in gradle and has a build.gradle file for it. Now, we would like to manage property of the project using groovy's config Sluper. And, I have placed config.groovy file in folder that contains all the Helper class for the project. The content of the conf.groovy file is below:
categories {
includeCategories = defaultIncludeCategories()
excludeCategories = defaultExcludeCategories()
}
String defaultIncludeCategories() {
def include = 'default'
if( isAbcJob() ) {
include = 'tier0'
}
logger.info "defaultIncludeCategories: $include"
include
}
Now, as you can see there is a method name isAbcJob() that I need to use in the configuration file but this method is present in build.gradle, which is the file that call conf.groovy file for property management.
Bottom line is how would conf.groovy script would know where isAbcJob() method is?
Please advice.
I found the following question that has been asked on Gradle forums very helpful. And, it looks like that accessing other gradle script's methods is not possible unless you access them through tasks:
https://discuss.gradle.org/t/multiple-apply-froms-dont-seem-to-import-all-methods/2274/6

Overriding CDocument OnFileSave()

How do I do this? If you could please kindly include the code for message map and the function itself, that would be greatly appreciated.
EDIT:
More specifically I am wondering how OnFileSave() links to OnSaveDocument(LPCSTR lpszPathName)
How does OnFileSave get lpszPathName?
You don't need to do anything special to override OnSaveDocument(...) it's already a virtual function in CDocument, so your derived class can just declare virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); in it's header, then implement it in the document. Nothing is needed in the message map. OnSaveDocument will be called by the framework as part of OnFileSave which is a handler in the base class for ID_FILE_SAVE. The lpszPathName refers to m_strPathName when called by OnFileSafe, which is set when opening a file or by calling SetPathName. If it's empty when saving, the user is prompted for a file name.
CDocument::OnFileSave is the message handler for the Save menu command. To handle it yourself put this in your document class message map:
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
and add your function:
void CYOURDOCUMENT::OnFileSave()
{
CDocument::OnFileSave();
}
To see everything it does put a breakpoint in your function and start single-stepping.

move the reference to working directory using libgit2sharp

I want to change the reference to the working directory to a different place using LibGit2Sharp in a Visual C++ project. it seems to me that Repository::Init() with RepositoryOptions can set the working directory to a non-default place. What I am trying to do here, however, is to change the reference to the working directory for the repo AFTER it is created by Repository::Init(). Repository::Info::WorkingDirectory seems to a be read-only property, so I can't change it through this route.
Any thoughts on how to accomplish this? or the equivalent of git_repository_set_workdir() is not exposed in LibGit2Sharp.
What I am trying to do here, however, is to change the reference to the working directory for the repo AFTER it is created by Repository::Init().
Repository.Init() puts a folder under source control by creating a new repository on the filesystem. It returns an instance of the created repository.
The constructor of the Repository type gives you acces to an existing repository. This constructor accepts an optional RepositoryOptions parameter to override some options.
In order to fulfill your request I'd go with something like this
var path ="D:\path\to\your\repo";
using (var repo = Repository.Init(path)
{
// Do nothing here
}
var newWorkdir ="D:\path\to\your\other\working\directory";
var options = new RepositoryOptions { WorkingDirectoryPath = newWorkdir };
using (var repo = new Repository(path, options))
{
// Do YOUR amzing stuff ;-)
}
Update:
The config file of the repo does not have the worktree attribute set to the right place, and the new working directory does not have a .git file pointing to the repo folder, as what you would expect.
This is the expected behavior. Passing a RepositoryOptions type to the constructor temporarily overrides some settings of the Repository. Once the repo is disposed, those temporary settings are lost.
I check the libgit2sharp source code for repository.cs and happen to notice that when it calls git_repository_set_workdir, it only has two arguments, as opposed to three
The bound libgit2 method is invoked with three params, the third one being set to false, because we do not want to persist the temporary settings when instanciating a repository.
Back to your original question: "What I am trying to do here, however, is to change the reference to the working directory for the repo AFTER it is created by Repository::Init()."
This is currently not possible with LibGit2Sharp. However, it might be possible to make this happen DURING the call to Repository.Init() through the addition of an optional parameter. If this looks like something may fit your need, I'd suggest you to open an issue regarding this topic, or even better, send a Pull Request ;-)
Another option would be for you to manually set the core.worktree config variable to the expected location (You'd have to deal with the creation of the gitlink by yourself, though):
The code below demonstrates this last option:
var path ="D:\path\to\your\repo";
// Note the use of forward slashes here
var newWorkdir ="D:/path/to/your/other/working/directory";
using (var repo = Repository.Init(path)
{
repo.Config.Set("core.worktree", newWorkdir);
}
using (var repo = new Repository(path))
{
// Do YOUR amzing stuff ;-)
}
Update 2:
LibGit2Sharp has just been updated with PR #453.
Among other things, this makes repo.Init() accept a separate git directory, which should fit your requirements.

Custom Logback Appender - Prepending file header and making it rollover

The functionality that I need is writing a header line at the beginning of the configured log file. The log file should, in addition, get rolled over based on a time pattern (I'm talking logback 1.0.7).
So, I'm thinking of writing an Appender - although I'm not sure whether it's not a custom Layout that I actually need.
1) Appender
Per logback's documentation, the right approach is to extend AppenderSkeleton, but then how would I combine this with the RollingFileAppender (to make the file rollover?)
On the other hand, if I extend RollingFileAppender, what method do I override to just decorate the existing functionality? How do I tell it to write that particular String only at the beginning of the file?
2) Layout
Analogously, the approach seems to be extending LayoutBase, and providing an implementation for doLayout(ILoggingEvent event).
But again, I don't know how to just decorate the behaviour - just adding a new line in the file, rather than disrupting its functionality (because I still want the rest of the logs to show up properly).
The getFileHeader() in LayoutBase looks promising, but how do I use it? Is it even intended to be overridden by custom layouts? (probably yes, since it's part of the Layout interface, but then how?)
Thank you!
Here I am answering my own question, just in case someone else comes across the same problem.
This is how I eventually did it (don't know however if it's the orthodox way):
Instead of extending AppenderSkeleton, I extended RollingFileAppender (to keep the rollover functionality), and overrode its openFile() method. In here I could manipulate the log file and write the header in it, after letting it do whatever it needed to do by default. Like this:
public void openFile(String fileName) throws IOException {
super.openFile(fileName);
File activeFile = new File(getFile());
if (activeFile.exists() && activeFile.isFile() && activeFile.length() == 0) {
FileUtils.writeStringToFile(activeFile, header);
}
}
I configured the header in logback.xml, as simple as this: <header> value </header>. This injects it in the header field of my new appender.
Seems to work without problems, but please do post if you know a better way!
Your solution has a problem: it deletes the first line of log of each new file. I think this is because you write the header whereas the file is open by logback.
I've found another solution that does not have this problem:
public void openFile(String fileName) throws IOException
{
super.openFile(fileName);
File activeFile = new File(getFile());
if (activeFile.exists() && activeFile.isFile() && activeFile.length() == 0)
{
lock.lock();
try
{
new PrintWriter(new OutputStreamWriter(getOutputStream(), StandardCharsets.UTF_8), true).println("your header");
}
finally
{
lock.unlock();
}
}
}

Resources