Change some fields in a file - ruby

I need to analyses a file and change some fields.
Example:
<taskdef uri="xxxxxx" resource="/mnt/data/yyy.xml">
<classpath path="/mnt/data/test.jar"/>
</taskdef>
<target name="test"
description="this is a xml file">
<fileset dir="/tmp/data/output/test_1/" includes=all/>
In my case I need to find this part:
<fileset dir="/tmp/data/output/test_1/" includes=all/>
and change just the name (for example) test_1
At the end, save the file

In your comment you say you "cannot use libraries like Nogokiri to parse the file". So I can only guess you're not doing full XML parsing.
Assuming you do not have to parse XML you could just use Ruby's String.replace method on the line in question. Just iterate over the lines in the file until you get to the one in quesion and call replace. Here's some pseudocode.
open file
for each line
is this what I want to change
change line
save (new) file

Related

How to use an msbuild CopyTask to copy a list of directories recursively

I would like to copy a list of directories recursively using a CopyTask.
The list is defined by a macro like so;
<ConanBinaryDirectories>some/path/;another/path/;</ConanBinaryDirectories>
I know a CopyTask can copy a single directory recursively, but how to deal with the specified format.
The ConanBinaryDirectories seems to be a MSBuild Property. If so, I assume you can use Msbuild Property Functions to get the single path.
Something like this:
<PropertyGroup>
<ConanBinaryDirectories>C:\Users\xxx\Desktop\Path1;C:\Users\xxx\Desktop\Path2;</ConanBinaryDirectories>
</PropertyGroup>
<PropertyGroup>
<SourcePath1>$(ConanBinaryDirectories.Split(";")[0])</SourcePath1> //C:\Users\xxx\Desktop\Path1
<SourcePath2>$(ConanBinaryDirectories.Split(";")[1])</SourcePath2> //C:\Users\xxx\Desktop\Path2
</PropertyGroup>
After you get the property which represents the single directory, you can use either 1.Copy task or 2.Exec task with xcopy command in it like this to copy the single directory to destination path.
All you need to do is to call the corresponding task twice in your custom target.
I know maybe what you want when you ask this question is a way like turn the MSBuild property to an MSBuild Item as the input of a task and do the copy job. But after my check: 1. The msbuild copy task actually doesn't support the input format like this some/path/ 2.We can use something like some/path/**/*.*, but it doesn't work well when our input could be something like #(...)/**/*.*.
So I suggest you split the macro to several paths and then use them into copy job.
Update:
The msbuild property doesn't support wildcard well. So to use something like **/*.*, you need to use Item instead of Property. You can have a look at this similar issue.
For a Property whose value is Path/*.*, it only represents a string Path/*.* most of the time while for an Item <MyItem Include="Path/*.*"/>, it represents all the files in the specified path. So no matter which way(copy task or xcopy command) we choose to do the copy job,the input should be an Item.
The script which works after test:
<PropertyGroup>
C:\Users\xxx\Desktop\Path1;C:\Users\xxx\Desktop\Path2
<PropertyGroup>
<SourcePath1>$(ConanBinaryDirectories.Split(";")[0])</SourcePath1>
<SourcePath2>$(ConanBinaryDirectories.Split(";")[1])</SourcePath2>
</PropertyGroup>
<ItemGroup>
<MySourceFiles Include="$(SourcePath1)\**\*.*" />
<MySourceFiles Include="$(SourcePath2)\**\*.*" />
</ItemGroup>
<Target Name="TestItem" AfterTargets="build">
<Copy SourceFiles="#(MySourceFiles)" DestinationFolder="$(OutputPath)"/>
</Target>
$(OutputPath) for C#, $(OutDir) for C++.

The <sequential> type doesn't support nested text data ("\")

I am executing an ANT target where I write to copy a zip file from 1 folder to another folder. For copying a list of files I have used a "for" loop. While executing this I am facing this issue:
The <sequential> type doesn't support nested text data ("\").
My script in the target is as follows:
<for param="MyZipParameter" list="${FilesInsideZipFile}" delimiter=";">
<sequential>
<if>
<matches string="#{MyZipParameter}" pattern="UpdateSite*" />
<then>
I am facing the issue during starting of "if" block in the script. I thought some invisible characters might be there and I have removed the script and without copying I have typed the script again, but still same the issue occurs during execution.
This totally blocked my work and I could not find any clue on this. Please help and provide your inputs.

Why is there a need for a separate item in my MSBuild file?

There are many articles (like this and this) that show how to add files to be published, and they all say to add something like this to the publish profile (.pubxml):
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\Extra Files\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
Why is there a need for the new _CustomFiles item? Why not simply <FilesForPackagingFromProject Include="..\Extra Files\**\*">? I tried it, and for some reason this causes every file in the project to end up in the deployed Extra Files folder. Can someone explain me this behaviour please?
Since you are asking about why this is required, I will have to dive deep into what this code means to explain what you're seeing. <Message /> is our friend!
The meaning of %
Let's first look at what % means by using it in a <Message> task:
<ItemGroup>
<_CustomFiles Include="..\Extra Files\**\*" />
</ItemGroup>
<Message Text="File: %(_CustomFiles.Identity)" />
When you run this, you'll get the following output:
File: ..\Extra Files\file1.txt
File: ..\Extra Files\file2.txt
File: ..\Extra Files\file3.txt
...
File: ..\Extra Files\etc.txt
Basically, the Message task runs once for each item in the item group, because we used %.
What's in the item group?
Let's take a peek at the item group before we even make any changes to it. When this task begins, FilesForPackagingFromProject already has all of the files in them, with various metadata properties, including DestinationRelativePath. Let's see it by adding just this to our task:
<Message Text="File: %(FilesForPackagingFromProject.Identity) -> %(FilesForPackagingFromProject.DestinationRelativePath)" />
This outputs:
File: ..\obj\TempBuildDir\PrecompiledApp.config -> PrecompiledApp.config
File: ..\obj\TempBuildDir\Web.config -> Web.config
File: ..\obj\TempBuildDir\App_Themes\theme.css -> App_Themes\theme.css
...
It's important to realise that this item group is not empty to begin with. You are trying to add items to it.
The working code
When you have sub-elements in an element that has %, they apply once to each iteration, so let's now look at the working code:
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<Message Text="File: %(FilesForPackagingFromProject.Identity) -> %(FilesForPackagingFromProject.DestinationRelativePath)" />
For each item in _CustomFiles, we include it into the FilesForPackagingFromProject item group and set the DestinationRelativePath metadata property to the appropriate RecursiveDir/Filename values - basically the ones that apply for the current element being looked at. Let's look at what this outputs:
File: ..\obj\TempBuildDir\PrecompiledApp.config -> PrecompiledApp.config
File: ..\obj\TempBuildDir\Web.config -> Web.config
File: ..\obj\TempBuildDir\App_Themes\theme.css -> App_Themes\theme.css
...
File: ..\Extra Files\file1.txt -> Extra Files\file1.txt
File: ..\Extra Files\file2.txt -> Extra Files\file2.txt
File: ..\Extra Files\file3.txt -> Extra Files\file3.txt
...
File: ..\Extra Files\etc.txt -> Extra Files\etc.txt
Including just a single file
If you wanted to include just a single file, you can do so as follows:
<FilesForPackagingFromProject Include="..\Extra Files\file1.txt">
<DestinationRelativePath>Extra Files\file1.txt</DestinationRelativePath>
</FilesForPackagingFromProject>
This has no % to expand anywhere, so it does exactly what you would expect: it includes a single file into the output.
The broken code
Now let's try to include a single file, but without hard-coding the path and instead using the % expression from the original code:
<FilesForPackagingFromProject Include="..\Extra Files\file1.txt">
<DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
<Message Text="File: %(FilesForPackagingFromProject.Identity) -> %(FilesForPackagingFromProject.DestinationRelativePath)" />
There are % here so things get expanded, but because this doesn't have a % in the item group element, the expansion works differently and things get pear-shaped:
File: ..\obj\TempBuildDir\PrecompiledApp.config -> PrecompiledApp.config
File: ..\obj\TempBuildDir\Web.config -> Web.config
File: ..\obj\TempBuildDir\App_Themes\theme.css -> App_Themes\theme.css
...
File: ..\Extra Files\file1.txt -> Extra Files\PrecompiledApp.config
File: ..\Extra Files\file1.txt -> Extra Files\Web.config
File: ..\Extra Files\file1.txt -> Extra Files\theme.css
So instead of adding file1.txt to the item group once, it iterates over the entire collection and adds file1.txt once for each file already in it. RecursiveDir is not set in this context, while Filename/Extension are the original filename of each file in the group.
Hopefully you can see now that this will create a file for each file in your entire deployment, but in a flat tree, and notably, the contents will be that of file1.txt rather than the original file.
When you include a wildcard instead of just one file, the same thing happens for every file matched by the wildcard.
How to fix this
Stick with the %(_CustomFiles) fix. Hopefully you will now see why it's necessary and how it does what it does. I do believe this is how you are supposed to do this: here's another question about it, with an answer that recommends this approach.

Creating a self extracting bash script for linux using Ant on Windows

I'm trying to generate a self extracting script using the method discussed here: http://www.linuxjournal.com/node/1005818
Using ANT (on windows) I create the payload archive using TAR task(gzip compression), and concat the script and the tar using the following CONCAT task.
<concat destfile="${output}/selfextract.bsx"
append="true"
eol="lf">
<fileset file="${installer}/decompress"/>
<fileset file="${output}/payload.tar.gz"/>
</concat>
The file is being created, and appears to contain the archive data, but when run on our Red Hat machine gzip complains "invalid compressed data --format violated".
Has anyone succeeded in this before?
Unless you use the fixlastline argument (off by default) then eol isn't used.
Likely guess: you have an extra line at the end of your "decompress" script after the __ARCHIVE_BELOW__ line. You can't have any extra (even empty) lines there or you'll pipe those bytes into the tar. This could be caused, as Dennis said, by eol problems, but you'd have to have an awk that isn't GNU to have this problem I think.
Easy way to confirm is change your tail to redirect to a file instead of tar, then hexdump the first few bytes of the original tar and the output tar to see what extra (or missing) bytes are getting in there.
A final thing to check is do you need to set the binary option in your concat.
Solved.
Higher in the ANT script, I was using the FixCRLF task with eol="unix" on decompress.sh. By default this task adds an extra newline to the end of the file unless you add fixlast="false".
I also added the binary="yes" attribute to concat.
My mistake for not including the rest of the script, and thanks for the help.
Final Code:
<concat destfile="${output}/selfextract.bsx"
binary="yes">
<fileset file="${installer}/decompress"/>
<fileset file="${output}/payload.tar.gz"/>
</concat>

How to get Chirpy to update mashed files when edits are made

I've just begun using Chirpy, and it's frigging amazing. One problem I'm having is that I'm unable to get it to update the mashed file(s) when an edit is made in one of the "sub" files.
IE: If I have a mashed file called "site.css" (via my js.chirp.config file) which contains "elements.css", "master.css", "misc.css" etc. And I make an edit to one of them (say, master.css), I want chirpy to kick in and redo the site.css with the new edits.
Is this at all possible?
Chirpy does this - just make sure your paths use backslashes rather than forward slashes.
<root>
<FileGroup Name="site.css">
<File Path="css\elements.css" />
<File Path="css\master.css" />
<File Path="css\misc.css" />
</FileGroup>
</root>
Chirpity chirp chirp chirp.
I have
<Folder Pattern="*.min.css" Minify="false" />
And with that wildcard in there, it doesnt run when min.css files are updated. I have to update the config and save for the mash to occur

Resources