Subject: [bug#27438] [PATCH] guix: build: ruby-build-system: Install to the vendor directory

From: Christopher Baines <[email-masked]>
Date: Sun, 16 Jul 2017 18:40:14 +0100

From: Christopher Baines <[email-masked]>

* guix/build/ruby-build-system.scm (install): Install gems to the vendor
  directory, rather than the GEM_HOME. The vendor directory does not include
  the version of ruby used to install the gem in the path, which makes it
  easier to add it to the GEM_PATH for all versions of ruby to use.
* gnu/packages/ruby.scm (ruby,ruby-2.1)[native-search-paths]: Switch to
  lib/ruby/vendor_ruby.
---
 gnu/packages/ruby.scm            | 12 ++----------
 guix/build/ruby-build-system.scm | 38 +++++++++++++++++++++++---------------
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm
index 7eba68444..f634d5e71 100644
--- a/gnu/packages/ruby.scm
+++ b/gnu/packages/ruby.scm
@@ -93,9 +93,7 @@
     (native-search-paths
      (list (search-path-specification
             (variable "GEM_PATH")
-            (files (list (string-append "lib/ruby/gems/"
-                                        (version-major+minor version)
-                                        ".0"))))))
+            (files (list (string-append "lib/ruby/vendor_ruby"))))))
     (synopsis "Programming language interpreter")
     (description "Ruby is a dynamic object-oriented programming language with
 a focus on simplicity and productivity.")
@@ -159,13 +157,7 @@ a focus on simplicity and productivity.")
                           "lib/mkmf.rb"
                           "process.c")
              (("/bin/sh") (which "sh"))))
-         %standard-phases)))
-    (native-search-paths
-     (list (search-path-specification
-            (variable "GEM_PATH")
-            (files (list (string-append "lib/ruby/gems/"
-                                        (version-major+minor version)
-                                        ".0"))))))))
+         %standard-phases)))))
 
 (define-public ruby-1.8
   (package (inherit ruby)
diff --git a/guix/build/ruby-build-system.scm b/guix/build/ruby-build-system.scm
index c2d276627..f4ce2e5d8 100644
--- a/guix/build/ruby-build-system.scm
+++ b/guix/build/ruby-build-system.scm
@@ -129,40 +129,48 @@ GEM-FLAGS are passed to the 'gem' invokation, if present."
                                          (assoc-ref inputs "ruby"))
                            1))
          (out (assoc-ref outputs "out"))
-         (gem-home (string-append out "/lib/ruby/gems/" ruby-version ".0"))
+         (vendor-dir (string-append out "/lib/ruby/vendor_ruby"))
          (gem-file (first-matching-file "\\.gem$"))
          (gem-file-basename (basename gem-file))
          (gem-name (substring gem-file-basename
                               0
-                              (- (string-length gem-file-basename) 4)))
-         (gem-directory (string-append gem-home "/gems/" gem-name)))
-    (setenv "GEM_HOME" gem-home)
-    (mkdir-p gem-home)
-    (and (apply system* "gem" "install" gem-file
-                "--local" "--ignore-dependencies"
-                ;; Executables should go into /bin, not /lib/ruby/gems.
-                "--bindir" (string-append out "/bin")
-                gem-flags)
+                              (- (string-length gem-file-basename) 4))))
+    (setenv "GEM_VENDOR" vendor-dir)
+    (and (let ((install-succeeded?
+                (zero?
+                 (apply system* "gem" "install" gem-file
+                        "--local" "--ignore-dependencies" "--vendor"
+                        ;; Executables should go into /bin, not
+                        ;; /lib/ruby/gems.
+                        "--bindir" (string-append out "/bin")
+                        gem-flags))))
+           (or install-succeeded?
+               (begin
+                 (simple-format #t "installation failed\n")
+                 (let ((failed-output-dir (string-append (getcwd) "/out")))
+                   (mkdir failed-output-dir)
+                   (copy-recursively out failed-output-dir))
+                 #f)))
          (begin
            ;; Remove the cached gem file as this is unnecessary and contains
            ;; timestamped files rendering builds not reproducible.
-           (let ((cached-gem (string-append gem-home "/cache/" gem-file)))
+           (let ((cached-gem (string-append vendor-dir "/cache/" gem-file)))
              (log-file-deletion cached-gem)
              (delete-file cached-gem))
            ;; For gems with native extensions, several Makefile-related files
            ;; are created that contain timestamps or other elements making
            ;; them not reproducible.  They are unnecessary so we remove them.
-           (if (file-exists? (string-append gem-directory "/ext"))
+           (if (file-exists? (string-append vendor-dir "/ext"))
                (begin
                  (for-each (lambda (file)
                              (log-file-deletion file)
                              (delete-file file))
                            (append
-                            (find-files (string-append gem-home "/doc")
+                            (find-files (string-append vendor-dir "/doc")
                                         "page-Makefile.ri")
-                            (find-files (string-append gem-home "/extensions")
+                            (find-files (string-append vendor-dir "/extensions")
                                         "gem_make.out")
-                            (find-files (string-append gem-directory "/ext")
+                            (find-files (string-append vendor-dir "/ext")
                                         "Makefile")))))
            #t))))
 
-- 
2.13.1