Hello!

I have been looking into how to update packages when new versions of some 
piece of software becomes available upstream. I wanted to use the debian uscan 
tool since it is already pretty mature and well maintained:-)

Attached you will find a script that does the following:

It expects a status file (simple name-value pairs, "name" and "version" is all 
that is required) as well as a watch file (debian/uscan syntax) and uses this 
information to check for updates. If a new version is available upstream, then
it will download a copy and generate the new hash for the file.

It will then process all *.tmpl files that it finds in the directory it is 
working on. All occurences of %{VERSION}%, %{NAME}%, %{OLD_VERSION}%, %{URL}% 
and %{HASH}% will be replaced within those template files.

The script will make sure to not overwrite existing files that were modified 
since it last ran.

In addition there is a --generate switch to help setting up a new package. If 
if finds an existing directory then it will move all the existing files to 
.tmpl-files. If the directory does not yet exist, then it will copy all files 
found in a template directory (default one needs to be set in the script for 
now). Afterwards it will generate status and watch files (which need to be 
edited, just like the templates). The idea is to help a bit getting started...

So what do you guys think?

Best Regards,
Tobias 
From 0e573dd2ec07a4734fd525b8a74732fc085671d4 Mon Sep 17 00:00:00 2001
From: Tobias Hunger <[email protected]>
Date: Wed, 9 Feb 2011 23:34:02 +0100
Subject: [PATCH] Pkgsetup script with example

---
 pkgs/build-support/pkgsetup/pkgsetup               |  323 ++++++++++++++++++++
 pkgs/development/libraries/qt-4.x/4.7/default.nix  |   13 +-
 .../libraries/qt-4.x/4.7/default.nix.tmpl          |  109 +++++++
 pkgs/development/libraries/qt-4.x/4.7/status       |    5 +
 pkgs/development/libraries/qt-4.x/4.7/watch        |    2 +
 5 files changed, 445 insertions(+), 7 deletions(-)
 create mode 100755 pkgs/build-support/pkgsetup/pkgsetup
 create mode 100644 pkgs/development/libraries/qt-4.x/4.7/default.nix.tmpl
 create mode 100644 pkgs/development/libraries/qt-4.x/4.7/status
 create mode 100644 pkgs/development/libraries/qt-4.x/4.7/watch

diff --git a/pkgs/build-support/pkgsetup/pkgsetup b/pkgs/build-support/pkgsetup/pkgsetup
new file mode 100755
index 0000000..e22a18f
--- /dev/null
+++ b/pkgs/build-support/pkgsetup/pkgsetup
@@ -0,0 +1,323 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use File::Basename;
+use File::Copy;
+use File::Path qw(make_path);
+use Getopt::Long;
+
+my $progname = basename($0);
+my $verbose = 0;
+
+my $templateDir = "/tmp/templates";
+
+# -------------------------------------------------------------------------
+# Helpers:
+# -------------------------------------------------------------------------
+
+sub l {
+    return unless $verbose;
+    my $message = shift;
+    print "$message";
+}
+
+sub usage {
+    print <<"EOF";
+Usage: $progname [options] [dir ...]
+  Process nix watchfiles in the directories listed.
+
+Options:
+    --generate     Generate a template nix package from scratch.
+
+    --verbose      Be verbose
+
+    --help         Print this help text
+    --version      Print version information
+EOF
+}
+
+sub version {
+    print <<"EOF";
+$progname, version 0.0.1
+EOF
+}
+
+sub hashFile
+{
+    my $output = shift;
+    
+    my $hash = `nix-hash --flat --type sha256 \"$output"`;
+    if ($? != 0) {
+        print "Failed to hash $output, skipping!\n";
+        return "";
+    }
+    chomp $hash;
+
+    l "Hash of $output: $hash\n";
+    return $hash;
+}
+
+sub updateFile
+{
+    my $input = shift;
+    my $output = shift;
+    my $replacements = shift;
+    my $originalHash = shift;
+
+    die "No hash passed to updateFile" unless defined $originalHash;
+
+    if (-e $output) {
+        my $hash = hashFile($output);
+
+        if ($hash ne $originalHash) {
+            l "New hash: $hash, old hash: $originalHash\n";
+            print "$output was modified, skipping!\n";
+            return "";
+        }
+    }
+
+    open IN, "<$input" or die "Failed to open $input for reading: $!";
+    open OUT, ">$output" or die "Failed to open $output for writing: $!";
+
+    print OUT "# This file was generated from $input by $0\n";
+    print OUT "# Please edit the template!\n\n";
+
+    while (<IN>) {
+        my $line = $_;
+        foreach my $i (keys %{$replacements}) {
+            my $value = $replacements->{$i};
+            my $key = uc $i;
+            $line =~ s/%\{$key\}%/$value/g;
+        }
+        print OUT $line;
+    }
+    
+    close OUT;
+    close IN;
+
+    my $hash = hashFile($output);
+    return $hash;
+}
+
+sub updateDirectory
+{
+    my $dir = shift;
+    my $replacements = shift;
+    my $hashes = shift;
+
+    opendir(DIR, "$dir");
+    my @files = grep(/\.tmpl$/, readdir(DIR));
+    closedir(DIR);
+
+    my %fileHashes;
+
+    foreach my $t (sort @files) {
+        l "Processing template $t...\n";
+        my $target = $t;
+        $target =~ s/\.tmpl$//;
+        my $originalHash = $hashes->{$target};
+        $originalHash = "" unless defined $originalHash;
+        $fileHashes{$target} = updateFile("$dir/$t", "$dir/$target", $replacements, $originalHash);
+    }
+    return %fileHashes;
+}
+
+sub generateInDirectory {
+    my $dir = shift;
+    die "No directory given" unless $dir;
+
+    l "Generating template in $dir...\n";
+
+    my @files;
+    if (!-d "$dir") {
+        # create target directory
+        make_path("$dir");
+
+        # populate directory with default templates (if any)
+        if (-d "$templateDir") {
+            opendir(DIR, "$templateDir");
+            @files = grep(/^[^\.]/, readdir(DIR));
+            closedir(DIR);
+        }
+        foreach my $f (@files) { l "Copying \"$templateDir/$f\" to \"$dir/$f\".\n"; copy("$templateDir/$f", "$dir/$f"); }
+    } else {
+        # copy original files to templates
+        opendir(DIR, $dir);
+        @files = grep(/^[^\.]/, readdir(DIR));
+        closedir(DIR);
+
+        foreach my $f (@files) { l "Copying \"$templateDir/$f\" to \"$dir/$f\".\n"; copy("$dir/$f", "$dir/$f.tmpl"); }
+        
+        # add a status file
+        open STATUS, ">$dir/status";
+        print STATUS "name = SOMENAME\nversion = 0\n";
+        close STATUS;
+
+        # add watch file
+        open WATCH, ">$dir/watch";
+        print WATCH "version=3\nhttp://some.url/\n";;
+        close WATCH;
+    }
+}
+
+sub processDirectory {
+    my $dir = shift;
+    die "No directory given" unless $dir;
+
+    my $statusFile = "$dir/status";
+    my $watchFile = "$dir/watch";
+
+    l "Checking prerequisites in $dir...\n";
+
+    die "Directory \"$dir\" does not exist." unless -d "$dir";
+    die "No status file found in \"$dir\"." unless -r "$statusFile";
+    die "No watch file found in \"$dir\"." unless -r "$watchFile";
+
+    l "Reading status file.\n";
+
+    my %status;
+    open STATUS, "<$statusFile" or die "Failed to read $statusFile: $!";
+    while (<STATUS>) {
+        my $line = $_;
+        chomp $line;
+
+        $line =~ s/#(.*)$//;
+        $line =~ s/^\s+//;
+        $line =~ s/\s+$//;
+        next unless $line;
+
+        (my $key, my $value) = split /\s*=\s*/, $line, 2;
+        $value = "" unless $value;
+        $status{lc $key} = $value;
+    }
+    close STATUS;
+
+    die "No package name \"name\" given in $statusFile." unless $status{name};
+    $status{version} = 0 unless $status{version};
+
+    l "Running uscan.\n";
+    my @result = `uscan --no-conf --watchfile \"$watchFile\" --upstream-version \"$status{version}\" --package \"$status{name}\" --destdir \"$dir\" --download --no-symlink`;
+
+    # parse uscan output:
+    my $newVersion = $status{version};
+    my $newUrl = "";
+    my $newFile = "";
+    my $notCurrent = 0;
+    
+    foreach my $l (@result) {
+        chomp $l;
+        l "Parsing USCAN line: $l\n";
+
+        if ($l =~ /=> Package is up to date/) {
+            l "    ^UP TO DATE^\n";
+            print "$dir: Package is up to date.\n";
+            return;
+        }
+        if ($l =~ /Successfully downloaded updated package (.*)$/) {
+            l "    ^FILE^\n";
+            $newFile = $1;
+            next;
+        }
+        if ($l =~ /Newer version \((.*)\) available on remote site:$/) {
+            l "    ^VERSION^\n";
+            $newVersion = $1;
+            next;
+        }
+        if ($l =~ /remote site does not even have current version/) {
+            l "    ^NO CURRENT^\n";
+            $notCurrent = 1;
+            next;
+        }
+        if ($newVersion ne $status{version}) {
+            next if $newUrl;
+            next unless $l =~ /^  /;
+            l "    ^URL^\n";
+            $newUrl = $l;
+            $newUrl =~ s/^\s*//;
+            next;
+        }
+    }
+
+    if ($? != 0) {
+        print "$dir: Failed to run uscan. Exit code was: $?.\n";
+        return;
+    }
+
+    l "New version: $newVersion\n";
+    l "New URL: $newUrl\n";
+
+    # Sanity checks:
+    if ($notCurrent) {
+        print "$dir: Remote site does not have ".$status{version}.". Newest there is: $newVersion\n";
+        return;
+    }
+
+    l "Generate new hash...\n";
+
+    die "No new file downloaded..." unless $newFile;
+    my $newHash = hashFile("$dir/$newFile");
+    l "Hash of new download: $newHash\n";
+    unlink("$dir/$newFile");
+
+    l "Process templates in $dir...\n";
+    
+    my %replacements = (
+        OLD_VERSION => $status{version},
+        NAME => $status{name},
+        VERSION => $newVersion,
+        URL => $newUrl,
+        HASH => $newHash
+    );
+
+    my %hashes = %status;
+    delete $hashes{version};
+    delete $hashes{name};
+
+    my %fileHashes = updateDirectory($dir, \%replacements, \%hashes);
+
+    l "Update $statusFile...\n";
+    
+    open STATUS, ">$statusFile" or die "Failed to update $statusFile: $!";
+    print STATUS "name = ".$status{name}."\n";
+    print STATUS "version = $newVersion\n\n";
+    print STATUS "# Hashes of files generated from the templates:\n";
+    foreach my $f (sort keys %fileHashes) {
+        my $base = basename($f);
+        print STATUS "$base=".$fileHashes{$f}."\n";
+    }
+    close STATUS;
+
+    l "Done with $dir.\n";
+}
+
+# -------------------------------------------------------------------------
+# Parse Options:
+# -------------------------------------------------------------------------
+
+my ($opt_h, $opt_v, $opt_verbose, $opt_generate);
+
+GetOptions("help" => \$opt_h,
+           "version" => \$opt_v,
+           "verbose!" => \$opt_verbose,
+           "generate!" => \$opt_generate)
+    or die "Usage: $progname [options]\nRun $progname --help for more details\n";
+
+if ($opt_h) { usage(); exit 0; }
+if ($opt_v) { version(); exit 0; }
+
+$verbose = 1 if ($opt_verbose);
+
+# -------------------------------------------------------------------------
+# Process directories:
+# -------------------------------------------------------------------------
+
+my @dirs = @ARGV;
+push @dirs, "." unless scalar(@dirs);
+
+foreach my $d (@dirs) {
+    if ($opt_generate) { generateInDirectory($d); }
+    else { processDirectory($d); }
+}
+
+exit 0;
diff --git a/pkgs/development/libraries/qt-4.x/4.7/default.nix b/pkgs/development/libraries/qt-4.x/4.7/default.nix
index 3a16679..21a70e6 100644
--- a/pkgs/development/libraries/qt-4.x/4.7/default.nix
+++ b/pkgs/development/libraries/qt-4.x/4.7/default.nix
@@ -1,3 +1,6 @@
+# This file was generated from nixpkgs/pkgs/development/libraries/qt-4.x/4.7/default.nix.tmpl by nixpkgs/pkgs/build-support/watchfile/watchfile
+# Please edit the template!
+
 { stdenv, fetchurl
 , alsaLib, gstreamer, gstPluginsBase, pulseaudio
 , libXft, libXrender, randrproto, xextproto, libXinerama, xineramaproto, libXcursor, libXmu
@@ -7,16 +10,12 @@
 , perl, coreutils, libXi
 , buildDemos ? false, buildExamples ? false, useDocs ? true}:
 
-let
-  v = "4.7.0";
-in
-
 stdenv.mkDerivation rec {
-  name = "qt-${v}";
+  name = "qt-4.7.1";
 
   src = fetchurl {
-    url = "ftp://ftp.qt.nokia.com/qt/source/qt-everywhere-opensource-src-${v}.tar.gz";;
-    sha256 = "0mbr7sjaswkd5gibyb36mlaas049fj8vf2risi66fzfac3amclp0";
+    url = "ftp://ftp.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.1.tar.gz";;
+    sha256 = "8cb5277c41f824cfc6dcee0e95e0bf23a9ad2c8d18d245105137481d092b124a";
   };
 
   preConfigure = ''
diff --git a/pkgs/development/libraries/qt-4.x/4.7/default.nix.tmpl b/pkgs/development/libraries/qt-4.x/4.7/default.nix.tmpl
new file mode 100644
index 0000000..09734b1
--- /dev/null
+++ b/pkgs/development/libraries/qt-4.x/4.7/default.nix.tmpl
@@ -0,0 +1,109 @@
+{ stdenv, fetchurl
+, alsaLib, gstreamer, gstPluginsBase, pulseaudio
+, libXft, libXrender, randrproto, xextproto, libXinerama, xineramaproto, libXcursor, libXmu
+, libXv, libXext, libXfixes, inputproto, fixesproto, libXrandr, freetype, fontconfig
+, zlib, libjpeg, libpng, libmng, which, mesa, openssl, dbus, cups, pkgconfig, libtiff, glib
+, mysql, postgresql, sqlite
+, perl, coreutils, libXi
+, buildDemos ? false, buildExamples ? false, useDocs ? true}:
+
+stdenv.mkDerivation rec {
+  name = "%{NAME}%-%{VERSION}%";
+
+  src = fetchurl {
+    url = "ftp://ftp.qt.nokia.com/qt/source/qt-everywhere-opensource-src-%{VERSION}%.tar.gz";;
+    sha256 = "%{HASH}%";
+  };
+
+  preConfigure = ''
+    export LD_LIBRARY_PATH="`pwd`/lib:$LD_LIBRARY_PATH"
+    configureFlags+="
+      -docdir $out/share/doc/${name}
+      -plugindir $out/lib/qt4/plugins
+      -importdir $out/lib/qt4/imports
+      -examplesdir $out/share/doc/${name}/examples
+      -demosdir $out/share/doc/${name}/demos
+      -datadir $out/share/${name}
+      -translationdir $out/share/${name}/translations
+    "
+  '';
+
+  propagatedBuildInputs = [
+    alsaLib
+    sqlite
+    libXft
+    libXrender
+    libXrandr
+    libXi
+    randrproto
+    xextproto
+    libXinerama
+    xineramaproto
+    libXcursor
+    zlib
+    libjpeg
+    libmng
+    mysql
+    postgresql
+    libpng
+    which
+    mesa
+    libXmu
+    libXv
+    openssl
+    dbus.libs
+    cups
+    pkgconfig
+    libXext
+    freetype
+    fontconfig
+    inputproto
+    fixesproto
+    libXfixes
+    glib
+    libtiff
+    gstreamer
+    gstPluginsBase
+    pulseaudio
+  ];
+
+  buildInputs = [ perl ];
+
+  prefixKey = "-prefix ";
+
+  configureFlags = ''
+    -v -no-separate-debug-info -release -fast -confirm-license -opensource
+    -system-zlib -system-libpng -system-libjpeg -qt-gif -system-libmng
+    -opengl -xrender -xrandr -xinerama -xcursor
+    -plugin-sql-mysql -system-sqlite
+    -qdbus -cups -glib -xfixes -dbus-linked -openssl-linked
+    -fontconfig -I${freetype}/include/freetype2
+    -exceptions -xmlpatterns
+    -multimedia -audio-backend -phonon -phonon-backend
+    -webkit -javascript-jit
+    -make libs -make tools -make translations
+    ${if buildDemos == true then "-make demos" else "-nomake demos"}
+    ${if buildExamples == true then "-make examples" else "-nomake examples"}
+    ${if useDocs then "-make docs" else "-nomake docs"}'';
+
+  prePatch = ''
+    substituteInPlace configure --replace /bin/pwd pwd
+    substituteInPlace src/corelib/global/global.pri --replace /bin/ls ${coreutils}/bin/ls
+    sed -e 's@/\(usr\|opt\)/@/var/empty/@g' -i config.tests/*/*.test -i mkspecs/*/*.conf
+  '';
+
+  postInstall = ''
+    ${if useDocs then "rm -rfv $out/share/doc/${name}/{html,src}" else ""}
+    ln -sv phonon $out/include/Phonon'';
+
+  enableParallelBuilding = true;
+
+  meta = with stdenv.lib; {
+    homepage = http://qt.nokia.com/products;
+    description = "A cross-platform application framework for C++";
+    license = "GPL/LGPL";
+    maintainers = with maintainers; [ urkud sander ];
+    platforms = platforms.linux;
+    priority = 10;
+  };
+}
diff --git a/pkgs/development/libraries/qt-4.x/4.7/status b/pkgs/development/libraries/qt-4.x/4.7/status
new file mode 100644
index 0000000..31b6976
--- /dev/null
+++ b/pkgs/development/libraries/qt-4.x/4.7/status
@@ -0,0 +1,5 @@
+name = qt
+version = 4.7.1
+
+# Hashes of files generated from the templates:
+default.nix=a396e6f9a34618672de28bd1eca111fd7b93c51ac7f95f86f213b1c4de4ffa97
diff --git a/pkgs/development/libraries/qt-4.x/4.7/watch b/pkgs/development/libraries/qt-4.x/4.7/watch
new file mode 100644
index 0000000..9c43ebd
--- /dev/null
+++ b/pkgs/development/libraries/qt-4.x/4.7/watch
@@ -0,0 +1,2 @@
+version=3
+ftp://ftp.qt.nokia.com/qt/source/qt-everywhere-opensource-src-(.*)\.tar\.gz
-- 
1.7.2.3

_______________________________________________
nix-dev mailing list
[email protected]
https://mail.cs.uu.nl/mailman/listinfo/nix-dev

Reply via email to