[PATCH 1/2] Move specification->package to gnu/packages.scm.

2014-08-31 Thread Cyril Roelandt
* guix/scripts/build.scm (specification->package): Move from here...
* gnu/packages.scm: ... to here.
---
 gnu/packages.scm   | 26 +-
 guix/scripts/build.scm | 23 +--
 2 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/gnu/packages.scm b/gnu/packages.scm
index 14ad755..26d87c6 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -28,6 +28,7 @@
   #:use-module (ice-9 vlist)
   #:use-module (ice-9 match)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-26)
   #:use-module (srfi srfi-39)
   #:export (search-patch
@@ -45,7 +46,9 @@
 package-transitive-dependents
 package-covering-dependents
 
-check-package-freshness))
+check-package-freshness
+
+specification->package))
 
 ;;; Commentary:
 ;;;
@@ -326,3 +329,24 @@ but ~a is available upstream~%")
   (case key
 ((getaddrinfo-error ftp-error) #f)
 (else (apply throw key args))
+
+(define (specification->package spec)
+  "Return a package matching SPEC.  SPEC may be a package name, or a package
+name followed by a hyphen and a version number.  If the version number is not
+present, return the preferred newest version."
+  (let-values (((name version)
+(package-name->name+version spec)))
+(match (find-best-packages-by-name name version)
+  ((p)  ; one match
+   p)
+  ((p x ...); several matches
+   (warning (_ "ambiguous package specification `~a'~%") spec)
+   (warning (_ "choosing ~a from ~a~%")
+(package-full-name p)
+(location->string (package-location p)))
+   p)
+  (_; no matches
+   (if version
+   (leave (_ "~A: package not found for version ~a~%")
+  name version)
+   (leave (_ "~A: unknown package~%") name))
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 5e4647d..09401e9 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -33,7 +33,7 @@
   #:use-module (srfi srfi-26)
   #:use-module (srfi srfi-34)
   #:use-module (srfi srfi-37)
-  #:autoload   (gnu packages) (find-best-packages-by-name)
+  #:autoload   (gnu packages) (specification->package)
   #:autoload   (guix download) (download-to-store)
   #:export (%standard-build-options
 set-build-options-from-command-line
@@ -41,27 +41,6 @@
 
 guix-build))
 
-(define (specification->package spec)
-  "Return a package matching SPEC.  SPEC may be a package name, or a package
-name followed by a hyphen and a version number.  If the version number is not
-present, return the preferred newest version."
-  (let-values (((name version)
-(package-name->name+version spec)))
-(match (find-best-packages-by-name name version)
-  ((p)  ; one match
-   p)
-  ((p x ...); several matches
-   (warning (_ "ambiguous package specification `~a'~%") spec)
-   (warning (_ "choosing ~a from ~a~%")
-(package-full-name p)
-(location->string (package-location p)))
-   p)
-  (_; no matches
-   (if version
-   (leave (_ "~A: package not found for version ~a~%")
-  name version)
-   (leave (_ "~A: unknown package~%") name))
-
 (define (register-root store paths root)
   "Register ROOT as an indirect GC root for all of PATHS."
   (let* ((root (string-append (canonicalize-path (dirname root))
-- 
1.8.4.rc3




[PATCH 2/2] scripts: add guix lint

2014-08-31 Thread Cyril Roelandt
* guix/scripts/lint.scm: New file. Defines a 'lint' tool for Guix packages.
* tests/lint.scm: New file.
* Makefile.am (MODULES, SCM_TESTS): Add them.
* po/guix/Makevars: Update appropriately.
* po/guix/POTFILES.in: Update appropriately.
* doc/guix.texi: Document "guix lint".
---
 Makefile.am   |   4 +-
 doc/guix.texi |  29 ++-
 guix/scripts/lint.scm | 213 ++
 po/guix/Makevars  |   3 +-
 po/guix/POTFILES.in   |   1 +
 tests/lint.scm| 110 ++
 6 files changed, 357 insertions(+), 3 deletions(-)
 create mode 100644 guix/scripts/lint.scm
 create mode 100644 tests/lint.scm

diff --git a/Makefile.am b/Makefile.am
index fff5958..371b85c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -89,6 +89,7 @@ MODULES = \
   guix/scripts/authenticate.scm\
   guix/scripts/refresh.scm \
   guix/scripts/system.scm  \
+  guix/scripts/lint.scm\
   guix.scm \
   $(GNU_SYSTEM_MODULES)
 
@@ -159,7 +160,8 @@ SCM_TESTS = \
   tests/nar.scm\
   tests/union.scm  \
   tests/profiles.scm   \
-  tests/syscalls.scm
+  tests/syscalls.scm   \
+  tests/lint.scm
 
 SH_TESTS = \
   tests/guix-build.sh  \
diff --git a/doc/guix.texi b/doc/guix.texi
index e34a70f..748480a 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -1459,7 +1459,10 @@ definitions like the one above may be automatically 
converted from the
 Nixpkgs distribution using the @command{guix import} command.}, the
 package may actually be built using the @code{guix build} command-line
 tool (@pxref{Invoking guix build}).  @xref{Packaging Guidelines}, for
-more information on how to test package definitions.
+more information on how to test package definitions, and
+@ref{Invoking guix lint}, for information on how to check a definition
+for style conformance.
+
 
 Eventually, updating the package definition to a new upstream version
 can be partly automated by the @command{guix refresh} command
@@ -2328,6 +2331,7 @@ programming interface of Guix in a convenient way.
 * Invoking guix download::  Downloading a file and printing its hash.
 * Invoking guix hash::  Computing the cryptographic hash of a file.
 * Invoking guix refresh::   Updating package definitions.
+* Invoking guix lint::  Finding errors in package definitions.
 @end menu
 
 @node Invoking guix build
@@ -2705,6 +2709,29 @@ for in @code{$PATH}.
 
 @end table
 
+@node Invoking guix lint
+@section Invoking @command{guix lint}
+The @command{guix lint} is meant to help package developers avoid common
+errors and use a consistent style.  It runs a few checks on a given set of
+packages in order to find common mistakes in their definitions.
+
+The general syntax is:
+
+@example
+guix lint @var{options} @var{package}@dots{}
+@end example
+
+If no package is given on the command line, then all packages are checked.
+The @var{options} may be zero or more of the following:
+
+@table @code
+
+@item --list-checkers
+@itemx -l
+List and describe all the available checkers that will be run on packages
+and exit.
+
+@end table
 
 @c *
 @node GNU Distribution
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
new file mode 100644
index 000..e3b0697
--- /dev/null
+++ b/guix/scripts/lint.scm
@@ -0,0 +1,213 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2014 Cyril Roelandt 
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see .
+
+(define-module (guix scripts lint)
+  #:use-module (guix base32)
+  #:use-module (guix packages)
+  #:use-module (guix records)
+  #:use-module (guix ui)
+  #:use-module (guix utils)
+  #:use-module (gnu packages)
+  #:use-module (ice-9 match)
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-9)
+  #:use-module (srfi srfi-11)
+  #:use-module (srfi srfi-37)
+  #:export (guix-lint
+check-inputs-should-be-native
+check-patches
+check-synopsis

Re: [PATCH] profiles: Report about upgrades.

2014-08-31 Thread Jason Self
Ludovic Courtès:
> Perhaps even a different format, like, say:
>
>   The following package will be upgraded:
> guile 1.8.8 → 2.0.9out /gnu/store/...
>
> Thoughts?

I like that. :)


Re: guix 0.7 installation

2014-08-31 Thread Ludovic Courtès
Federico Beffa  skribis:

> $ guix package 
> --install={autoconf,automake,bzip2,gcc-toolchain,gettext,guile,libgcrypt,pkg-config,sqlite}
>
> and got the packages installed :-)
> At the end of the process I've been told to define the following
> environment variables:
>
>export PKG_CONFIG_PATH="/home/beffa/.guix-profile/lib/pkgconfig"
>export ACLOCAL_PATH="/home/beffa/.guix-profile/share/aclocal"
>
> On top of those I've defined the PATH as follows:
>
> export PATH=$HOME/.guix-profile/bin:$PATH
>
> The README file mentions all of the following veriables: ACLOCAL_PATH,
> CPATH, LIBRARY_PATH, PKG_CONFIG_PATH. However, only the above ones
> have been mentioned during the installation phase and defined.

Indeed, ‘guix package’ should have told you about LIBRARY_PATH and
CPATH, but there was a bug in the ‘gcc-toolchain’ package, which commit
d474d5d fixes.

Now it would additionally list:

  export CPATH="$HOME/.guix-profile/include"
  export LIBRARY_PATH="$HOME/.guix-profile/lib"

> configure:3474: checking whether the C compiler works
> configure:3496: gccconftest.c  >&5
> ld: cannot find crt1.o: No such file or directory
> ld: cannot find crti.o: No such file or directory
> collect2: error: ld returned 1 exit status

This is due to the lack of the above LIBRARY_PATH setting.

Could you try setting and report back?

Thanks for the report!

Ludo’.



Re: New x86 machine

2014-08-31 Thread Ludovic Courtès
Hi Sergio,

Sergio Durigan Junior  skribis:

> On Friday, August 29 2014, Ludovic Courtès wrote:
>
>> For that, we’ll need volunteers to help with:
>>
>>   1. general sysadmin work.
>
> Hey Ludo :-).
>
> I can help with this if needed.

That would be appreciated!  The first thing to do would be to subscribe
to guix-sysadmin.

Then we really need to streamline sysadmins work so we can efficiently
share work, have clear procedures, etc.

For instance, we should agree on who can access the slaves (currently it
depends on the machine), how to avoid stepping on each other’s toes when
doing something on the front-end, things like that.  There’s a lot of
room for improvement here, and I think it’s about time to do something
about it.  :-)

So if you or anyone else has experience with this, or ideas on how to
best organize, I’m all ears.

Ludo’.



Re: [PATCH] profiles: Report about upgrades.

2014-08-31 Thread Ludovic Courtès
Alex Kost  skribis:

> But is it correct to report it like that?  I mean if a user has
> “guile-1.8.8” and installs “guile-2.0.9” then (with your variant) he
> gets:
>
> The following package will be upgraded:
>guile-2.0.9out /gnu/store/...
>
> I thought it should be:
>
> The following package will be upgraded:
>guile-1.8.8out /gnu/store/...
>
> Actually that's why (to avoid possible confusion) I initially suggested:
>
> The following package will be upgraded (removed):
>guile-1.8.8out /gnu/store/...
>
> The following package will be installed:
>guile-2.0.9out /gnu/store/...

Oh I see, I had misunderstood the intent.

Well, I don’t know what’s best.  I’m happy with the way things are now,
though I can see why it could be confusing.

Perhaps even a different format, like, say:

  The following package will be upgraded:
guile 1.8.8 → 2.0.9out /gnu/store/...

Thoughts?

Ludo’.



Re: guix-shell?

2014-08-31 Thread Ludovic Courtès
David Thompson  skribis:

> I think it would be nice to have a default file that guix environment
> searches for if none is specified.  Tools like Ruby's bundler
> automatically use a file called 'Gemfile'.  Perhaps guix environment
> could look for an 'environment.scm' file by default?

Yes, why not.

Ludo’.



Re: Merging guix.el

2014-08-31 Thread Ludovic Courtès
Alex Kost  skribis:

> Ludovic Courtès (2014-08-29 00:09 +0400) wrote:

[...]

> OK, I made "emacs.am" and modified "configure.ac" and "Makefile.am" (I
> pushed 2 new commits to “emacs-ui” branch).  Is there anything else to
> be done in a build part?

No, that looks good to me.

[...]

>>> I think it's a good idea, but if that "name" is just a package name,
>>> I can't use this optimization: I need to define entries by
>>> "name+version".
>>
>> Yes, makes sense.  So that ‘name->entries’ field would map a package
>> name to a list of entries; in the most common case, there’ll be just one
>> entry anyway.  How does that sound?

[...]

> Also I'm still not sure about the name ‘manifest-name->entries’ (or
> ‘manifest-name->entry’), as this function returns a vhash, it does not
> transform a name into a list of entries.  It may be confusing, no?

That would be only for internal use anyway, but if you prefer
‘manifest-table’ would do as well.

[...]

 Given that ‘set-packages!’ has only on call site, what about removing
 it, and instead writing directly:

   (define %packages
 (fold-packages ... vlist-null))

   (define %package-count
 (length %packages))

   (define %package-table
 (vlist-fold ...))

 It’s also best to prefix global variable names with ‘%’.
>
> I recalled why I used that ugly ‘set-packages!’: I just didn't want to
> count packages again (i.e. to use ‘length’) for hash-table, so I
> combined setting ‘packages’ variable with counting.

OK, but even when there’s 1M packages, ‘length’ is still going to be
almost instantaneous, so no worries IMO.  ;-)

>> I would make %package-table a vhash instead of a hash table:
>>
>>   (define %package-table
>> (vlist-fold (lambda (elem result)
>>   (match elem
>> ((name . package)
>>  (vhash-cons (cons (package-name package)
>>(package-version package))
>>  package
>>  (if (vhash-assq name result)
>>  ...)
>> vlist-null
>> %packages))
>
> ... I left hash table, because I still don't understand how to use vhash
> for that: a name+version key should give a list of all matching
> packages, but AFAIU your variant would just replace one package with
> another (with the same name+version).

The key is ‘vhash-fold*’ (info "(guile) VHashes").  It allows you to
traverse all the entries associated with a given key:

--8<---cut here---start->8---
scheme@(guile-user)> (vhash-cons '("guile" "2.0") 'foo
 (vhash-cons '("guile" "2.0") 'bar
 vlist-null))
$12 = #
scheme@(guile-user)> (vhash-fold* cons '() '("guile" "2.0") $12)
$13 = (bar foo)
--8<---cut here---end--->8---

I think that answers your question, right?

> As for ‘set-current-manifest-maybe!’, I'm afraid it can't be deleted.  I
> found that I put it in some places where it shouldn't appear and I fixed
> that, but it still stays in functions returning “package information”
> for the elisp side (for info/list buffers).  Currently I can't invent a
> way how to get rid of this function completely.

I think the profile’s file name could be kept on the elisp side, and
passed to the Scheme code, which wouldn’t need to keep it in a global
variable.  That would also allow guix.el to be used on profiles other
than the default one.

That said, we can look into it later if you prefer.  WDYT?

Thanks!

Ludo’.



[PATCH] Add an 'optimiseStore' RPC

2014-08-31 Thread Ludovic Courtès
Hi Eelco,

The patch below adds an ‘optimiseStore’ RPC, and thus adds a mandatory
‘optimiseStore’ method in ‘StoreAPI’.

OK to commit?

Ludo’.

diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 09639e7..4404ffc 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -168,6 +168,9 @@ public:
files with the same contents. */
 void optimiseStore(OptimiseStats & stats);
 
+/* Generic variant of the above method.  */
+void optimiseStore();
+
 /* Optimise a single store path. */
 void optimisePath(const Path & path);
 
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index d833f3a..68acb6e 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -169,6 +169,24 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
 }
 }
 
+static string showBytes(unsigned long long bytes)
+{
+return (format("%.2f MiB") % (bytes / (1024.0 * 1024.0))).str();
+}
+
+void LocalStore::optimiseStore()
+{
+OptimiseStats stats;
+
+optimiseStore(stats);
+
+printMsg(lvlError,
+format("%1% freed by hard-linking %2% files; there are %3% files with equal contents out of %4% files in total")
+% showBytes(stats.bytesFreed)
+% stats.filesLinked
+% stats.sameContents
+% stats.totalFiles);
+}
 
 void LocalStore::optimisePath(const Path & path)
 {
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 4619206..8e1bfdb 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -564,6 +564,13 @@ void RemoteStore::clearFailedPaths(const PathSet & paths)
 readInt(from);
 }
 
+void RemoteStore::optimiseStore()
+{
+openConnection();
+writeInt(wopOptimiseStore, to);
+processStderr();
+readInt(from);
+}
 
 void RemoteStore::processStderr(Sink * sink, Source * source)
 {
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 04b60fc..b9b7f7c 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -82,7 +82,9 @@ public:
 PathSet queryFailedPaths();
 
 void clearFailedPaths(const PathSet & paths);
-
+
+void optimiseStore();
+
 private:
 AutoCloseFD fdSocket;
 FdSink to;
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index b635fee..3109f10 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -250,6 +250,10 @@ public:
`nix-store --register-validity'. */
 string makeValidityRegistration(const PathSet & paths,
 bool showDerivers, bool showHash);
+
+/* Optimise the disk space usage of the Nix store by hard-linking files
+   with the same contents. */
+virtual void optimiseStore() = 0;
 };
 
 
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 9317f89..9a3d83a 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -43,6 +43,7 @@ typedef enum {
 wopQueryValidPaths = 31,
 wopQuerySubstitutablePaths = 32,
 wopQueryValidDerivers = 33,
+wopOptimiseStore = 34
 } WorkerOp;
 
 
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 8814fe3..413db20 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -650,6 +650,13 @@ static void performOp(bool trusted, unsigned int clientVersion,
 break;
 }
 
+case wopOptimiseStore:
+	startWork();
+	store->optimiseStore();
+	stopWork();
+	writeInt(1, to);
+	break;
+
 default:
 throw Error(format("invalid operation %1%") % op);
 }
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 341a4f6..e13bfe9 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -798,17 +798,6 @@ static void opRepairPath(Strings opFlags, Strings opArgs)
 }
 
 
-static void showOptimiseStats(OptimiseStats & stats)
-{
-printMsg(lvlError,
-format("%1% freed by hard-linking %2% files; there are %3% files with equal contents out of %4% files in total")
-% showBytes(stats.bytesFreed)
-% stats.filesLinked
-% stats.sameContents
-% stats.totalFiles);
-}
-
-
 /* Optimise the disk space usage of the Nix store by hard-linking
files with the same contents. */
 static void opOptimise(Strings opFlags, Strings opArgs)
@@ -816,17 +805,9 @@ static void opOptimise(Strings opFlags, Strings opArgs)
 if (!opArgs.empty() || !opFlags.empty())
 throw UsageError("no arguments expected");
 
-OptimiseStats stats;
-try {
-ensureLocalStore().optimiseStore(stats);
-} catch (...) {
-showOptimiseStats(stats);
-throw;
-}
-showOptimiseStats(stats);
+store->optimiseStore();
 }
 
-
 static void opQueryFailedPaths(Strings opFlags, Strings opArgs)
 {
 if (!opArgs.empty() || !opFlags.empty())