I want to create a nuget package that contains only what is specified in my nuspec file, but still get the version from my csproj. In order to use the token I have to pack like:
nuget pack MyProj.csproj
But when I do it like this it adds some dependencies and creates an unwanted folder in my nuget package. My nuspec file is:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Test</id>
<version>$version$</version>
<title>Test</title>
<authors>Test</authors>
<owners>Test</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Test</description>
<summary>Test</summary>
<releaseNotes>Test</releaseNotes>
<copyright>Test</copyright>
</metadata>
<files>
<file src="bin\Debug\*.dll" target="lib\net45" />
<file src="bin\Debug\MyProj.Wpf.exe" target="lib\net45" />
<file src="bin\Debug\MyProj.Wpf.exe.config" target="lib\net45" />
</files>
</package>
When I run the pack command the file it adds extra is the MyProj.Wpf.exe in the target="lib\net452"
Can I force it not to add the dependencies and this extra file? Or to do only what is specified in nuspec?
It's been a while since I posted this question. Since then I used a solution that worked for me, so I'm going to post it here for anyone that needs it.
I created a .csproj that modifies the .nuspec file and sets it's version according to the assembly file of the .csproj. To reduce the manual work I created a .bat file that called this .exe with arguments and finished creating the installer. I used Squirrel.Windows for the installer creation.
I created a NuspectVersionSetter.csproj to set the nuspec version. There are many ways to implement this, here goes a simple one:
static void Main(string[] args)
{
try
{
if (args.Length < 2)
{
throw new Exception("Args are not correct");
}
var assemblyFilePath = args[0];
var nuspecFilePath = args[1];
IsFileValid(assemblyFilePath, ".cs");
IsFileValid(nuspecFilePath, ".nuspec");
var version = GetAssemblyVersion(assemblyFilePath);
if (string.IsNullOrEmpty(version))
{
throw new Exception("Unable to get version");
}
WriteNuspec(nuspecFilePath, version);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
static void WriteNuspec(string path, string version)
{
var lines = File.ReadAllLines(path);
string versionLine = null;
for(var i = 0; i < lines.Length; ++i)
{
var line = lines[i];
if (line.Contains("<version>") && line.Contains("</version>"))
{
var init = line.IndexOf("<version>") + "<version>".Length;
var end = line.IndexOf("</version>");
line = line.Remove(init, end - init);
lines[i] = line.Insert(init, version);
break;
}
}
File.WriteAllLines(path, lines);
}
static void IsFileValid(string file, string extension)
{
if (!File.Exists(file))
{
throw new Exception("Invalid file path: " + file);
}
if (!file.EndsWith(extension))
{
throw new Exception("Invalid file extension: " + file);
}
}
static string GetAssemblyVersion(string path)
{
var lines = File.ReadAllLines(path);
foreach(var line in lines)
{
if(line.Contains("AssemblyVersion") && !line.Contains(".*"))
{
var parts = line.Split('\"');
if (parts.Length != 3)
{
break;
}
return parts[1];
}
}
foreach (var line in lines)
{
if (line.Contains("AssemblyFileVersion") && !line.Contains(".*"))
{
var parts = line.Split('\"');
if (parts.Length != 3)
{
break;
}
return parts[1];
}
}
foreach (var line in lines)
{
if (line.Contains("AssemblyInformationalVersion") && !line.Contains(".*"))
{
var parts = line.Split('\"');
if (parts.Length != 3)
{
break;
}
return parts[1];
}
}
throw new Exception("Unable to get version");
}
As explained before the .bat file also wrapped the Squirrel.Windows installer creation.
Small observations about the .bat:
NuspecVersionSetter was the .exe created from the .csproj above
This example assumes your NuspecVersionSetter.exe is inside a folder in your .csproj, therefore some paths may need to be adjusted
The Squirrel.Windows version is old in this example, you many need to change it
The .bat file I used was the following:
NuspecVersionSetter ../Properties/AssemblyInfo.cs mynuspec.nuspec
nuget pack
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=*" %%G in ('dir *.nupkg /b /a-d /od') do (
SET newest=%%G
)
"../../packages/squirrel.windows.1.2.1/tools/Squirrel" --releasify !newest! -g installing.gif
If there are any questions about this answer, ask them in the comments.
Related
I'm trying to add a custom handler to my site to redirect to the appropriate Sitemap for the current language, i.e. mysite.com/sitemap.xml --> sitemap-en.xml, mysite.es/sitemap.xml --> sitemap-es.xml, etc.
This is my setup:
handler trigger patch:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<customHandlers>
<handler trigger="sitemap.xml" handler="sitemap.ashx" />
</customHandlers>
</sitecore>
</configuration>
web.config:
<add path="sitemap.ashx" verb="*" type="MySite.CustomSitecore.Handlers.SitemapHandler,MySite" name="SitemapXml" />
handler:
namespace MySite.CustomSitecore.Handlers
{
public class SitemapHandler : IHttpHandler
{
public bool IsReusable
{
get
{
throw new NotImplementedException();
}
}
public void ProcessRequest(HttpContext context)
{
try
{
var curSite = Sitecore.Context.Site;
var m_Sites = SitemapManagerConfiguration.GetSites();
foreach (DictionaryEntry site in m_Sites)
{
if (site.Key.ToString().Equals(curSite.Name))
{
var filepath = site.Value;
HttpContext.Current.Response.Redirect("/" + filepath, false);
return;
}
}
return;
}
catch (Exception ex)
{
Log.Info("Error in SitemapHandler: " + ex, this);
}
}
}
}
It's not working though, when I try to go to mysite.com/sitemap.xml and debug it steps through the redirect process as expected and looks as if it should be successfully redirecting to /sitemap-en.xml, but the page just spins and displays browser error saying that the page can't be loaded.
I have tried a couple different redirect methods, but nothing has worked. I tried this as well:
HttpContext.Current.Response.StatusCode = 200;
HttpContext.Current.Response.ContentType = "text/xml";
HttpContext.Current.Response.AddHeader("Location", "/" + filepath);
HttpContext.Current.Response.End();
return;
Not sure if this is the issue, But out of the box Sitecore don't allow .xml files. Security hardening.
You can use somethings like this in the config, to add the .xml extension
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<preprocessRequest help="Processors should derive from Sitecore.Pipelines.PreprocessRequest.PreprocessRequestProcessor">
<processor type="Sitecore.Pipelines.PreprocessRequest.FilterUrlExtensions, Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx, ashx, asmx, xml</param>
</processor>
</preprocessRequest>
</pipelines>
</sitecore>
</configuration>
But I think a better solution, use the default and take security seriously.
Tell the search engine what the url of the sitemap is by using a robots.txt
User-agent: *
Sitemap: /sitemap.ashx
I am following a tutorial about joomla 3 extension development. I am using Joomla 3.2.4
I have a plugin name clicktocall, which to make all phone number text displayed as a link.
Phone number format is XXXX-XXXX or XXXX XXXX, X is digit. and I want display any phone number as ">
The method is using pattern as replace any text match the pattern by link tag
I installed, enabled the plugin
I do it after a tutorial in an ebook, in the book everything are so smoothly, but in my site, after I view an article which have phone number text, there are nothing happen. The plugin not working.
My code:
clicktocall.php
defined('_JEXEC') or die;
jimport('joomla.plugin.plugin');
class plgContentClicktocall extends JPlugin {
function plgContentClicktocall(&$subject, $params) {
parent::__construct($subject, $params);
}
public function onContentPrepare($context, &$row, &$params, $page = 0) {
//don't run this when the content is indexing
if ($context == 'com_finder.indexer') {
return true;
}
if (is_object($row)) {
echo $row->text;
return $this->clickToCall($row->text, $params);
}
return $this->clickToCall($row, $params);
}
protected function clickToCall(&$text, &$params) {
// matches 4 numbers followed by an optional hyphen or space,
// then followed by 4 numbers.
// phone number is in the form XXXX-XXXX or XXXX XXXX
$pattern = '/(\W[0-9]{4})-? ?(\W[0-9]{4})/';
$replacement = '$1$2';
$text = preg_replace($pattern, $replacement, $text);
return true;
}
}
clicktocall.xml
<?xml version="1.0" encoding="UTF-8"?>
<extension
version="3.0"
type="plugin"
group="content"
method="upgrade">
<name>Content - Click To Call</name>
<author>Tim Plummer</author>
<creationDate>April 2013</creationDate>
<copyright>Copyright (C) 2013 Packt Publishing. All rights
reserved.</copyright>
<license> http://www.gnu.org/licenses/gpl-3.0.html</license>
<authorEmail>example#packtpub.com</authorEmail>
<authorUrl>http://packtpub.com</authorUrl>
<version>1.0.0</version>
<description>This plugin will replace phone numbers with click
to call links. Requires Joomla! 3.0 or greater.
Don't forget to publish this plugin!
</description>
<files>
<filename plugin="clicktocall">clicktocall.php</filename>
<filename>index.html</filename>
</files>
</extension>
index.html : blank tags only
Sorry for the XML, I try for 10 minutes to make it pre-formatted but seem to be useless, but I confirm it's OK, included all files in my plugin
I believe the issue is you are returning the value from your click2Call() method inside your onContentPrepare() method. Try reformatting like so:
public function onContentPrepare($context, &$row, &$params, $page = 0) {
//don't run this when the content is indexing
if ($context == 'com_finder.indexer') {
return true;
}
if (is_object($row)) {
echo $row->text;
$this->clickToCall($row->text, $params);
} else {
$this->clickToCall($row, $params);
}
return true;
}
Since the row variable is referenced, any changes you make to the row data you're making to the actual data. Therefor, no need to return any data outside of the the return true at the end of the method.
Hi I am developing an application to download an attachment from server and read those files using Blackberry 10 Cascades(QNX Momentics IDE) . I have downloaded the attachment but the attachment is a .Zip file. How can I unzip the folder? Does anyone have samples please share?
you can use quazip library for unzipping the archive, here quazip porting for Blackberry 10 cascades
https://github.com/hakimrie/quazip
here sample function to unzip a file using quazip to extract a file into /data/ folder
bool ZipUtils::extractArchive(QString m_filename) {
// check if file exists
QFile file(m_filename);
if (!file.exists()){
qDebug() << "file is not exists gan";
return false;
}
bool result = true;
QuaZip *m_zip = new QuaZip(m_filename);
QString dataFolder = QDir::homePath();
QString bookname = m_filename.split("/").last().split(".").first();
QString dest = dataFolder + "/" + bookname;
QDir dir(dest);
if (!dir.exists()) {
// create destination folder
dir.mkpath(".");
}
qDebug() << "destination folder: " + dest;
m_zip->open(QuaZip::mdUnzip);
if (!m_zip) {
return false;
}
QuaZipFile *currentFile = new QuaZipFile(m_zip);
int entries = m_zip->getEntriesCount();
int current = 0;
for (bool more = m_zip->goToFirstFile(); more; more =
m_zip->goToNextFile()) {
++current;
// if the entry is a path ignore it. Path existence is ensured separately.
if (m_zip->getCurrentFileName().split("/").last() == "")
continue;
QString outfilename = dest + "/" + m_zip->getCurrentFileName();
QFile outputFile(outfilename);
// make sure the output path exists
if (!QDir().mkpath(QFileInfo(outfilename).absolutePath())) {
result = false;
//emit logItem(tr("Creating output path failed"), LOGERROR);
qDebug() << "[ZipUtil] creating output path failed for:"
<< outfilename;
break;
}
if (!outputFile.open(QFile::WriteOnly)) {
result = false;
//emit logItem(tr("Creating output file failed"), LOGERROR);
qDebug() << "[ZipUtil] creating output file failed:" << outfilename;
break;
}
currentFile->open(QIODevice::ReadOnly);
outputFile.write(currentFile->readAll());
if (currentFile->getZipError() != UNZ_OK) {
result = false;
//emit logItem(tr("Error during Zip operation"), LOGERROR);
qDebug() << "[ZipUtil] QuaZip error:" << currentFile->getZipError()
<< "on file" << currentFile->getFileName();
break;
}
currentFile->close();
outputFile.close();
//emit logProgress(current, entries);
}
return result;
}
please make sure to update your pro file to include quazip library (assume your project & quazip project in the same workspace/folder):
INCLUDEPATH += ../src ../../quazip/src/
SOURCES += ../src/*.cpp
HEADERS += ../src/*.hpp ../src/*.h
LIBS += -lbbsystem
LIBS += -lbbdata
LIBS += -lz
lupdate_inclusion {
SOURCES += ../assets/*.qml
}
device {
CONFIG(release, debug|release) {
DESTDIR = o.le-v7
LIBS += -Bstatic -L../../quazip/arm/o.le-v7 -lquazip -Bdynamic
}
CONFIG(debug, debug|release) {
DESTDIR = o.le-v7-g
LIBS += -Bstatic -L../../quazip/arm/o.le-v7-g -lquazip -Bdynamic
}
}
simulator {
CONFIG(release, debug|release) {
DESTDIR = o
LIBS += -Bstatic -L../../quazip/x86/o-g/ -lquazip -Bdynamic
}
CONFIG(debug, debug|release) {
DESTDIR = o-g
LIBS += -Bstatic -L../../quazip/x86/o-g/ -lquazip -Bdynamic
}
}
I used the PKZIP 2.0 compatible archive handler from the OSDaB Project, it does the job quite nicely. They provide Zip and UnZip classes. You also need to include linkage to the installed compression library by adding -lz to the LIBS variable in your .pro file:
LIBS += -lz
Sample code:
UnZip unzip;
UnZip::ErrorCode ec = unzip.openArchive(fileName);
if (ec != UnZip::Ok) {
emit errorString(fileName + " could not open archive.");
} else {
QList<UnZip::ZipEntry> fileNames = unzip.entryList();
ec = unzip.extractAll(dirName);
if (ec != UnZip::Ok) {
emit errorString(
newFileName + " could not extract data to "
+ dirName);
} else {
UnZip::ZipEntry file;
foreach(file, fileNames) {
// do something with file if needed.
}
}
}
I'm creating my first gradle plugin. I'm trying to copy a file from the distribution jar into a directory I've created at the project. Although the file exists inside the jar, I can't copy it to the directory.
This is my task code:
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
class InitTask extends DefaultTask {
File baseDir;
private void copyEnvironment(File environments) {
String resource = getClass().getResource("/environments/development.properties").getFile();
File input = new File(resource);
File output = new File(environments, "development.properties");
try {
copyFile(input, output);
}
catch (IOException e) {
e.printStackTrace();
}
}
void copyFile(File sourceFile, File destFile) {
destFile << sourceFile.text
}
#TaskAction
void createDirectories() {
logger.info "Creating directory."
File environments = new File(baseDir, "environments");
File scripts = new File(baseDir, "scripts");
File drivers = new File(baseDir, "drivers");
[environments, scripts, drivers].each {
it.mkdirs();
}
copyEnvironment(environments);
logger.info "Directory created at '${baseDir.absolutePath}'."
}
}
And this is the error I'm getting:
:init
java.io.FileNotFoundException: file:/path-to-jar/MyJar.jar!/environments/development.properties (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at groovy.util.CharsetToolkit.<init>(CharsetToolkit.java:69)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.newReader(DefaultGroovyMethods.java:15706)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.getText(DefaultGroovyMethods.java:14754)
at org.codehaus.groovy.runtime.dgm$352.doMethodInvoke(Unknown Source)
at org.codehaus.groovy.reflection.GeneratedMetaMethod$Proxy.doMethodInvoke(GeneratedMetaMethod.java:70)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3465)
at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:61)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at br.com.smartcoders.migration.tasks.InitTask.copyFile(InitTask.groovy:29)
Just to emphasize, the development.properties is inside the environments directory inside the MyJar.jar
getClass().getResource() returns a URL. To access that URL, you'll have to read it directly (e.g. with url.text) rather than first converting it to a String/File. Or you can use getClass().getResourceAsStream().text, which is probably more accurate. In both cases you can optionally specify the file encoding.
Kotlin DSL answer!
For cases like this it is good to have extensions:
fun Any.getResource(filename: String): File? {
val input = this::class.java.classLoader.getResourceAsStream(filename) ?: return null
val tempFile = File.createTempFile(
filename.substringBeforeLast('.'),
"." + filename.substringAfterLast('.')
)
tempFile.deleteOnExit()
tempFile.writer().use { output ->
input.bufferedReader().use { input ->
output.write(input.readText())
}
}
return tempFile
}
Is there a relatively simple way in nant, without writing a custom task, to get the name of the newest folder in a certain directory? Recursion is not needed. I have been trying to do it with directory::get-creation-time and a foreach loop and if statements, yada yada. It's too complex, and I'm about to create a custom task instead. However, I suspect there is some simpler way to do it via existing nant features.
I believe you're correct in stating that doing this in a pure nant fashion might pose to be messy, especially the way properties work in nant. If you don't want to write a custom task, you can always use the script task. For example:
<?xml version="1.0"?>
<project name="testing" basedir=".">
<script language="C#" prefix="test" >
<code>
<![CDATA[
[Function("find-newest-dir")]
public static string FindNewestDir( string startDir ) {
string theNewestDir = string.Empty;
DateTime theCreateTime = new DateTime();
DateTime theLastCreateTime = new DateTime();
string[] theDirs = Directory.GetDirectories( startDir );
for ( int theCurrentIdx = 0; theCurrentIdx < theDirs.Length; ++theCurrentIdx )
{
if ( theCurrentIdx != 0 )
{
DateTime theCurrentDirCreateTime = Directory.GetCreationTime( theDirs[ theCurrentIdx ] );
if ( theCurrentDirCreateTime >= theCreateTime )
{
theNewestDir = theDirs[ theCurrentIdx ];
theCreateTime = theCurrentDirCreateTime;
}
}
else
{
theNewestDir = theDirs[ theCurrentIdx ];
theCreateTime = Directory.GetCreationTime( theDirs[ theCurrentIdx ] );
}
}
return theNewestDir;
}
]]>
</code>
</script>
<property name="dir" value="" overwrite="false"/>
<echo message="The newest directory is: ${test::find-newest-dir( dir )}"/>
</project>
With this, one should be able to call the function to get the newest directory. The implementation of the actual function could be changed to be anything (optimized a bit more or whatever), but I've included a quick one for reference on how to use the script task. It produces output like the following:
nant -D:dir=c:\
NAnt 0.85 (Build 0.85.2478.0; release; 10/14/2006)
Copyright (C) 2001-2006 Gerry Shaw
http://nant.sourceforge.net
Buildfile: file:///C:/tmp/NAnt.build
Target framework: Microsoft .NET Framework 2.0
[script] Scanning assembly "jdrgmbuy" for extensions.
[echo] The newest directory is: C:\tmp
BUILD SUCCEEDED
Total time: 0.3 seconds.