[sagemath] 03/03: Improve the state of post-install tests

Ximin Luo infinity0 at debian.org
Sat Jan 21 21:28:49 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository sagemath.

commit 5a3b08481e72cc202aaf13ad5dd430ec30b7bd41
Author: Ximin Luo <infinity0 at debian.org>
Date:   Sat Jan 21 20:13:37 2017 +0100

    Improve the state of post-install tests
    
    - split out test-analysis rules into a separate file and install them as
      examples for the main sagemath package
    - fix or disable some more tests
    - update README.Debian on how to run the tests
---
 debian/README.Debian                               | 13 +++--
 debian/README.source                               |  2 +-
 debian/adhoc/sage-env                              |  2 +-
 debian/changelog                                   |  6 ++
 debian/patches/d0-disable-jsmol.patch              |  4 +-
 debian/patches/d1-disable-post-install-tests.patch | 35 ++++++++++++
 debian/patches/d1-install-paths.patch              |  9 +--
 debian/patches/d1-multiarch-python-paths.patch     | 31 +++++++++++
 debian/patches/d1-sage-cli.patch                   | 23 +++++++-
 debian/patches/df-python_security.patch            |  2 +-
 debian/patches/series                              |  9 ++-
 debian/patches/u2-allow-override-sage-local.patch  |  8 +--
 .../patches/u2-fix-atrocious-symlink-logic.patch   | 32 +++++++++++
 debian/patches/u2-fix-trivial-test-cases.patch     | 11 ++++
 debian/rules                                       | 64 +++++++---------------
 debian/sagemath.examples                           |  1 +
 debian/tests.mk                                    | 51 +++++++++++++++++
 17 files changed, 234 insertions(+), 69 deletions(-)

diff --git a/debian/README.Debian b/debian/README.Debian
index 594a821..241cf83 100644
--- a/debian/README.Debian
+++ b/debian/README.Debian
@@ -51,11 +51,14 @@ code for this package (`apt-get source sagemath`), and make sure the Debian
 patches are applied. Then, from any directory:
 
  *$ export -n SAGE_LOCAL SAGE_ROOT
- *$ SAGE_SRC=/path/to/sage/src sage -t -p --long --logfile=ptestlong.log --all
-
-(Note: some doctests under SAGE_SRC/src/doc are known not to work with these
-instructions, due to upstream #21732. They do work when testing from a built
-source tree; see below.)
+ *$ SAGE_SRC=/path/to/sage/src \
+    SAGE_PKGS=/path/to/sage/build/pkgs \
+    sage -t -p --long --logfile=ptestlong.log --all
+
+It's recommended that you install *all* packages, including all documentation
+packages in all languages, when running these tests. Otherwise you will see
+more failures than necessary. They are easy to ignore, but every person that
+reads the results will have to figure this out, wasting time.
 
 Feel free to upload your test logs somewhere and send links to them to our
 mailing list <debian-science-sagemath at lists.alioth.debian.org>. Please do not
diff --git a/debian/README.source b/debian/README.source
index 3b3487c..bbd143e 100644
--- a/debian/README.source
+++ b/debian/README.source
@@ -114,7 +114,7 @@ There are three cases:
 
 You may also find this useful:
 
- $ debian/rules EXTRA_SAGE_TEST_FLAGS=-f override_dh_auto_test
+ $ debian/rules check-failed
 
 It will run all previously-failed tests again, which is useful if you're on a
 mass test-fixing spree and forget to count which ones you've fixed. However
diff --git a/debian/adhoc/sage-env b/debian/adhoc/sage-env
index edc19ca..93255e3 100644
--- a/debian/adhoc/sage-env
+++ b/debian/adhoc/sage-env
@@ -5,7 +5,7 @@ if [[ -z ${SAGE_ROOT} ]]; then
 fi
 
 if [[ -z ${SAGE_LOCAL} ]]; then
-	export SAGE_LOCAL="/usr/"
+	export SAGE_LOCAL="/usr"
 fi
 
 if [[ -z ${SAGE_DATA} ]]; then
diff --git a/debian/changelog b/debian/changelog
index 07d8c17..984ebec 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+sagemath (7.4-7) UNRELEASED; urgency=medium
+
+  * Improve the state of post-install tests.
+
+ -- Ximin Luo <infinity0 at debian.org>  Sat, 21 Jan 2017 20:13:24 +0100
+
 sagemath (7.4-6) unstable; urgency=medium
 
   * Only check dochtml.log for errors if we will actually build the doc
diff --git a/debian/patches/d0-disable-jsmol.patch b/debian/patches/d0-disable-jsmol.patch
index e1c58ce..e3c99b3 100644
--- a/debian/patches/d0-disable-jsmol.patch
+++ b/debian/patches/d0-disable-jsmol.patch
@@ -7,7 +7,7 @@ Author: Ximin Luo <infinity0 at debian.org>
 Forwarded: not-needed
 --- a/sage/src/sage/repl/ipython_kernel/install.py
 +++ b/sage/src/sage/repl/ipython_kernel/install.py
-@@ -113,23 +113,6 @@
+@@ -121,23 +121,6 @@
          dst = os.path.join(self.nbextensions_dir, 'mathjax')
          self.symlink(src, dst)
  
@@ -31,7 +31,7 @@ Forwarded: not-needed
      def _kernel_cmd(self):
          """
          Helper to construct the SageMath kernel command.
-@@ -235,7 +218,6 @@
+@@ -243,7 +226,6 @@
          """
          instance = cls()
          instance.use_local_mathjax()
diff --git a/debian/patches/d1-disable-post-install-tests.patch b/debian/patches/d1-disable-post-install-tests.patch
new file mode 100644
index 0000000..a8cf614
--- /dev/null
+++ b/debian/patches/d1-disable-post-install-tests.patch
@@ -0,0 +1,35 @@
+Description: Disable some post-install tests
+ We don't need to test these pre-install either because they're already
+ implicitly tested by other parts of the build process.
+Author: Ximin Luo <infinity0 at debian.org>
+Forwarded: not-needed
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/sage/src/sage/misc/sage_ostools.py
++++ b/sage/src/sage/misc/sage_ostools.py
+@@ -24,8 +24,6 @@
+         True
+         sage: have_program('there_is_not_a_program_with_this_name')
+         False
+-        sage: have_program('sage', path=SAGE_ROOT)
+-        True
+         sage: have_program('ls', path=SAGE_ROOT)
+         False
+     """
+--- a/sage/src/sage/all.py
++++ b/sage/src/sage/all.py
+@@ -279,14 +279,6 @@
+ 
+     The non-existence of this file will be used as a trigger to run
+     ``sage-starts`` during the Sage build.
+-
+-    TESTS:
+-
+-    Check that the file exists when Sage is running::
+-
+-        sage: started_file = os.path.join(SAGE_LOCAL, 'etc', 'sage-started.txt')
+-        sage: os.path.isfile(started_file)
+-        True
+     """
+     started_file = os.path.join(SAGE_LOCAL, 'etc', 'sage-started.txt')
+ 
diff --git a/debian/patches/d1-install-paths.patch b/debian/patches/d1-install-paths.patch
index b15c9d5..a7ed8bf 100644
--- a/debian/patches/d1-install-paths.patch
+++ b/debian/patches/d1-install-paths.patch
@@ -114,7 +114,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
  ### pkg-config setup
 --- a/sage/src/sage/repl/ipython_kernel/install.py
 +++ b/sage/src/sage/repl/ipython_kernel/install.py
-@@ -10,11 +10,11 @@
+@@ -10,11 +10,12 @@
  import errno
  
  from sage.env import (
@@ -124,11 +124,12 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
  )
  from jupyter_core.paths import ENV_JUPYTER_PATH
 -JUPYTER_PATH = ENV_JUPYTER_PATH[0]
-+JUPYTER_PATH = os.path.join(SAGE_SHARE, "jupyter")
++# if SAGE_SHARE is writeable, assume we're building the Debian package and the path is a dummy path that doesn't get installed
++JUPYTER_PATH = ENV_JUPYTER_PATH[0] if not os.access(SAGE_SHARE, os.W_OK) else os.path.join(SAGE_SHARE, "jupyter")
  
  
  class SageKernelSpec(object):
-@@ -109,7 +109,7 @@
+@@ -117,7 +118,7 @@
              sage: os.path.isdir(mathjax)
              True
          """
@@ -137,7 +138,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
          dst = os.path.join(self.nbextensions_dir, 'mathjax')
          self.symlink(src, dst)
  
-@@ -134,7 +134,7 @@
+@@ -142,7 +143,7 @@
               '{connection_file}']
          """
          return [
diff --git a/debian/patches/d1-multiarch-python-paths.patch b/debian/patches/d1-multiarch-python-paths.patch
new file mode 100644
index 0000000..0a19a5a
--- /dev/null
+++ b/debian/patches/d1-multiarch-python-paths.patch
@@ -0,0 +1,31 @@
+Description: Correctly handle Debian's python multiarch extension module names
+ We need to strip that part in order to return the correct ".pyx" filename.
+ Otherwise a few post-install tests break.
+Author: Ximin Luo <infinity0 at debian.org>
+Forwarded: not-needed
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/sage/src/sage/misc/sageinspect.py
++++ b/sage/src/sage/misc/sageinspect.py
+@@ -122,6 +122,7 @@
+ import tokenize
+ import types
+ import re
++import sysconfig
+ EMBEDDED_MODE = False
+ from sage.env import SAGE_SRC
+ 
+@@ -1247,7 +1248,12 @@
+     except TypeError: # this happens for Python builtins
+         return ''
+     if sourcefile.endswith(loadable_module_extension()):
+-        return sourcefile[:-len(loadable_module_extension())]+os.path.extsep+'pyx'
++        sourcefile = sourcefile[:-len(loadable_module_extension())]
++        # remove Debian's python multiarch extension module naming conventions
++        multiarchsuffix = "." + sysconfig.get_config_vars("MULTIARCH")[0]
++        if sourcefile.endswith(multiarchsuffix):
++            sourcefile = sourcefile[:-len(multiarchsuffix)]
++        return sourcefile+os.path.extsep+'pyx'
+     return sourcefile
+ 
+ def sage_getargspec(obj):
diff --git a/debian/patches/d1-sage-cli.patch b/debian/patches/d1-sage-cli.patch
index a88e171..7bd5988 100644
--- a/debian/patches/d1-sage-cli.patch
+++ b/debian/patches/d1-sage-cli.patch
@@ -593,10 +593,27 @@ Forwarded: not-needed
  --preparse
  --python
  -q
-@@ -215,19 +212,6 @@
+@@ -198,36 +195,6 @@
          sage: ret
          0
  
+-    Test ``sage --info [packages]`` and the equivalent
+-    ``sage -p --info --info [packages]`` (the doubling of ``--info``
+-    is intentional, that option should be idempotent)::
+-
+-        sage: out, err, ret = test_executable(["sage", "--info", "sqlite"])
+-        sage: print(out)
+-        Found local metadata for sqlite-...
+-        = SQLite =
+-        ...
+-        SQLite is a software library that implements a self-contained,
+-        serverless, zero-configuration, transactional SQL database engine.
+-        ...
+-        sage: err
+-        ''
+-        sage: ret
+-        0
+-
 -        sage: out, err, ret = test_executable(["sage", "-p", "--info", "--info", "sqlite"])
 -        sage: print(out)
 -        Found local metadata for sqlite-...
@@ -613,7 +630,7 @@ Forwarded: not-needed
      Test ``sage-run`` on a Python file, both with an absolute and with a relative path::
  
          sage: dir = tmp_dir(); name = 'python_test_file.py'
-@@ -414,50 +398,6 @@
+@@ -414,50 +381,6 @@
          ...
          RuntimeError: refusing to run doctests...
  
@@ -664,7 +681,7 @@ Forwarded: not-needed
      Test external programs being called by Sage::
  
          sage: (out, err, ret) = test_executable(["sage", "--sh"], "echo Hello World\nexit 42\n")
-@@ -599,32 +539,6 @@
+@@ -599,32 +522,6 @@
          sage: ret
          0
  
diff --git a/debian/patches/df-python_security.patch b/debian/patches/df-python_security.patch
index fea8a6d..a2bb4ca 100644
--- a/debian/patches/df-python_security.patch
+++ b/debian/patches/df-python_security.patch
@@ -35,7 +35,7 @@
          with open(os.devnull, 'w') as dev_null:
 --- a/sage/src/sage/tests/cmdline.py
 +++ b/sage/src/sage/tests/cmdline.py
-@@ -380,23 +380,24 @@
+@@ -363,23 +363,24 @@
          sage: ret
          1
  
diff --git a/debian/patches/series b/debian/patches/series
index 45fdac7..84b88b4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -23,13 +23,14 @@ u1-fix-preexec-fn.patch
 u1-fix-dont-require-DISPLAY.patch
 
 # Patches that should be upstreamed, but need a bit more work first
-u2-allow-override-sage-local.patch
+u2-reproducible-docs.patch
+u2-looser-doctest-basename.patch
+u2-fix-atrocious-symlink-logic.patch
 u2-fix-trivial-test-cases.patch
 u2-fix-less-trivial-test-cases.patch
 u2-fix-sympow-cachedir.patch
+u2-allow-override-sage-local.patch
 u2-scripts-dir.patch
-u2-reproducible-docs.patch
-u2-looser-doctest-basename.patch
 
 # Patch Sage to work with dependency Debian packages
 # These won't change even if Debian and Sage use the same version
@@ -55,7 +56,9 @@ d1-sage-cli.patch
 d1-sage-env.patch
 d1-fakeroot.patch
 d1-test-optional.patch
+d1-multiarch-python-paths.patch
 d1-doc-docs.patch
+d1-disable-post-install-tests.patch
 
 # Potentially controversial fixes
 # We had to do these to make things work, at some time in the past
diff --git a/debian/patches/u2-allow-override-sage-local.patch b/debian/patches/u2-allow-override-sage-local.patch
index 207fb73..a612c81 100644
--- a/debian/patches/u2-allow-override-sage-local.patch
+++ b/debian/patches/u2-allow-override-sage-local.patch
@@ -114,10 +114,10 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
  log.info('python_modules = {0}'.format(python_modules))
 --- a/sage/src/sage/repl/ipython_kernel/install.py
 +++ b/sage/src/sage/repl/ipython_kernel/install.py
-@@ -94,7 +94,7 @@
-         except OSError as err:
-             if err.errno == errno.EEXIST:
-                 return
+@@ -102,7 +102,7 @@
+                 pass
+             else:
+                 raise
 -        os.symlink(src, dst)
 +        os.symlink(os.path.relpath(src, os.path.dirname(dst)), dst)
  
diff --git a/debian/patches/u2-fix-atrocious-symlink-logic.patch b/debian/patches/u2-fix-atrocious-symlink-logic.patch
new file mode 100644
index 0000000..b98009a
--- /dev/null
+++ b/debian/patches/u2-fix-atrocious-symlink-logic.patch
@@ -0,0 +1,32 @@
+Description: Fix atrocious logic in symlink()
+ If the desired result is already in effect, do nothing. Otherwise, proceed
+ with the previous behaviour, but handle permissions errors correctly.
+ We don't actually need any part of this file in Debian, but fixing this (so
+ that post-install tests don't fail) was easier than trying to figure out if
+ removing the file would have other consequences elsewhere.
+Author: Ximin Luo <infinity0 at debian.org>
+Forwarded: TODO
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/sage/src/sage/repl/ipython_kernel/install.py
++++ b/sage/src/sage/repl/ipython_kernel/install.py
+@@ -89,11 +89,19 @@
+             sage: os.listdir(path)
+             ['b']
+         """
++        if os.path.islink(dst):
++            origsrc = os.path.join(os.path.dirname(dst), os.readlink(dst))
++            if os.path.abspath(origsrc) == os.path.abspath(src):
++                return
+         try:
+             os.remove(dst)
+         except OSError as err:
+             if err.errno == errno.EEXIST:
+                 return
++            elif err.errno == errno.ENOENT:
++                pass
++            else:
++                raise
+         os.symlink(src, dst)
+ 
+     def use_local_mathjax(self):
diff --git a/debian/patches/u2-fix-trivial-test-cases.patch b/debian/patches/u2-fix-trivial-test-cases.patch
index 2dd9219..05f7277 100644
--- a/debian/patches/u2-fix-trivial-test-cases.patch
+++ b/debian/patches/u2-fix-trivial-test-cases.patch
@@ -198,3 +198,14 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
          """
          r = os.popen('tachyon').read()
          if use_pager == True:
+--- a/sage/src/sage/tests/gap_packages.py
++++ b/sage/src/sage/tests/gap_packages.py
+@@ -102,7 +102,7 @@
+ 
+         sage: from sage.tests.gap_packages import all_installed_packages
+         sage: all_installed_packages()
+-        (...'GAPDoc',...)
++        (...'GAPDoc'...)
+     """
+     packages = []
+     for path in libgap.eval('GAP_ROOT_PATHS').sage():
diff --git a/debian/rules b/debian/rules
index 6138f17..0949635 100755
--- a/debian/rules
+++ b/debian/rules
@@ -99,7 +99,8 @@ override_dh_auto_build-arch: dh_auto_build-stamp
 # Otherwise we get spurious failures on some low-memory arch-any buildds.
 override_dh_auto_build-indep: dh_auto_build-stamp check-dochtml-log
 
-run_tests = cd sage && ./sage -t -p $(NUMJOBS) --all --long $(EXTRA_SAGE_TEST_FLAGS) --logfile=logs/ptestlong.log
+LOGFILE = sage/logs/ptestlong.log
+run_tests = cd sage && ./sage -t -p $(NUMJOBS) --all --long --logfile=logs/ptestlong.log
 override_dh_auto_test:
 	cd sage && $(SAGE_LOCAL)/bin/sage-starts
 ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
@@ -116,11 +117,27 @@ ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
 	if $(is_prerelease); then :; \
 	elif debian/rules -s had-few-failures; then :; else \
 	  debian/rules -s had-not-too-many-failures && \
-	  mv sage/logs/ptestlong.log sage/logs/ptestlong.log.1 && \
+	  mv $(LOGFILE) $(LOGFILE).1 && \
 	  { $(run_tests) -f; cd "$(CURDIR)" && debian/rules -s had-few-failures; }; \
 	fi
 endif
 
+TESTS_MK = $(MAKE) -s --no-print-directory -f debian/tests.mk LOGFILE=$(LOGFILE)
+failed-tests%:
+	@$(TESTS_MK) "$@"
+
+had-few-failures:
+	test -f $(LOGFILE)
+	test "$$($(TESTS_MK) failed-tests-total-normal)" -lt 80
+	test -z "$$($(TESTS_MK) failed-tests-special)"
+
+had-not-too-many-failures:
+	test -f $(LOGFILE)
+	test "$$($(TESTS_MK) failed-tests-total-normal)" -lt 120
+
+check-failed:
+	$(run_tests) -f
+
 override_dh_auto_install:
 	rm -rf debian/build/usr/var/tmp/sage/build
 # We built .pyo to make the docbuild/tests go faster, but as per Debian policy
@@ -222,49 +239,6 @@ build-dep: debian/control
 	if which aptitude >/dev/null; then sudo mk-build-deps -ir -t 'aptitude -R'; \
 	else sudo mk-build-deps -ir; fi
 
-had-few-failures:
-	# Allow < 80 tests to fail, but no "special" failures like Killed etc
-	test -f sage/logs/ptestlong.log
-	test "$$(debian/rules -s --no-print-directory failed-tests-total)" -lt 80
-
-had-not-too-many-failures:
-	test -f sage/logs/ptestlong.log
-	test "$$(grep "Failed example:" sage/logs/ptestlong.log | wc -l)" -lt 120
-
-FAILED_TESTS = grep '^sage -t .*  \#' sage/logs/ptestlong.log
-failed-tests:
-	$(FAILED_TESTS)
-
-failed-tests-total:
-	grep "Failed example:" sage/logs/ptestlong.log | wc -l
-	$(FAILED_TESTS) | { ! grep '# [^0-9]'; }
-
-failed-tests-by-name:
-	$(FAILED_TESTS) | sort '-t#' -k1
-
-failed-tests-by-count:
-# Sort "special" failures last, e.g. segfault/abort/timed-out etc
-	$(FAILED_TESTS) \
-	  | sed -e 's,#\(\s\s*[^0-9]\),#9999999\1,g' \
-	  | sort '-t#' -k2n,2n \
-	  | sed -e 's,9999999,,g'
-
-failed-tests-by-error:
-# Filter out NameError; most of these are caused by earlier errors
-	grep '\(Error\|Warning\):' sage/logs/ptestlong.log \
-	  | grep -v NameError \
-	  | sort | uniq -c | sort -k1n,1n
-
-FT_CAUSE_ERRORTYPE = \(Error\|Warning\)
-FT_CAUSE_BACKTRACE = 2
-failed-tests-by-cause:
-	grep -B$$((2 * $(FT_CAUSE_BACKTRACE))) -Z '$(FT_CAUSE_ERRORTYPE):' sage/logs/ptestlong.log \
-	  | sed -e 's/^--$$/\x00/g' \
-	  | sed -z -e 's/^\s*//g' \
-	  | tr '\0\n' '\n\t' \
-	  | sort | uniq -c | sort -k1n,1n \
-	  | less -S +G
-
 get-orig-source:
 	debian/rules ../sagemath_$(DEB_VERSION_UPSTREAM).orig.tar.xz
 
diff --git a/debian/sagemath.examples b/debian/sagemath.examples
new file mode 100644
index 0000000..487bbd3
--- /dev/null
+++ b/debian/sagemath.examples
@@ -0,0 +1 @@
+debian/tests.mk
diff --git a/debian/tests.mk b/debian/tests.mk
new file mode 100755
index 0000000..5f84810
--- /dev/null
+++ b/debian/tests.mk
@@ -0,0 +1,51 @@
+#!/usr/bin/make -f
+# Makefile containing shell snippets to help with running sage tests and
+# analysing the output.
+#
+# TODO: eventually call this from an autopkgtest
+
+SAGE = sage
+SAGE_TEST_FLAGS =
+LOGFILE = ptestlong.log
+
+check:
+	$(SAGE) -t -p --all --long --logfile=$(LOGFILE) $(SAGE_TEST_FLAGS)
+
+check-failed:
+	$(SAGE) -t -p --all --long --logfile=$(LOGFILE) -f $(SAGE_TEST_FLAGS)
+
+FAILED_TESTS = grep '^sage -t .*  \#' $(LOGFILE)
+failed-tests:
+	$(FAILED_TESTS)
+
+failed-tests-total-normal:
+	grep "Failed example:" $(LOGFILE) | wc -l
+
+failed-tests-special:
+	$(FAILED_TESTS) | grep '# [^0-9]' || true
+
+failed-tests-by-name:
+	$(FAILED_TESTS) | sort '-t#' -k1
+
+failed-tests-by-count:
+# Sort "special" failures last, e.g. segfault/abort/timed-out etc
+	$(FAILED_TESTS) \
+	  | sed -e 's,#\(\s\s*[^0-9]\),#9999999\1,g' \
+	  | sort '-t#' -k2n,2n \
+	  | sed -e 's,9999999,,g'
+
+failed-tests-by-error:
+# Filter out NameError; most of these are caused by earlier errors
+	grep '\(Error\|Warning\):' $(LOGFILE) \
+	  | grep -v NameError \
+	  | sort | uniq -c | sort -k1n,1n
+
+FT_CAUSE_ERRORTYPE = \(Error\|Warning\)
+FT_CAUSE_BACKTRACE = 2
+failed-tests-by-cause:
+	grep -B$$((2 * $(FT_CAUSE_BACKTRACE))) -Z '$(FT_CAUSE_ERRORTYPE):' $(LOGFILE) \
+	  | sed -e 's/^--$$/\x00/g' \
+	  | sed -z -e 's/^\s*//g' \
+	  | tr '\0\n' '\n\t' \
+	  | sort | uniq -c | sort -k1n,1n \
+	  | less -S +G

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sagemath.git



More information about the debian-science-commits mailing list