Antti Kultanen wrote:
> # dpkg -i git_1.7.7-1_amd64.deb
> (Reading database ... 433269 files and directories currently installed.)
> Preparing to replace git 1:1.7.6.3-1 (using git_1.7.7-1_amd64.deb) ...
> Unpacking replacement git ...
> dpkg: error processing git_1.7.7-1_amd64.deb (--install):
> unable to make backup link of `./usr/lib/git-core/git-merge-ours' before
> installing new version: Too many links
Ah, thanks.
It should be possible to reproduce the bug in 1.7.6.3-1 that that
patch fixed by simply reinstalling git 1.7.6.3-1 --- it is the version
of git being replaced that is relevant. The simplest workaround to
recover is to remove git and then install the new version (and then to
confirm the fix by reinstalling it).
To allow people to upgrade from the broken state without removing git
in between, we'll need to remove some of the hard links _before_
upgrading (i.e., in "preinst upgrade"). I don't know how to feel
about that. A part of me wants to think:
- the low and idiosyncratic hardlink limit is a btrfs bug.
- btrfs is effectively experimental still. Generally speaking, btrfs
users probably know how to recover from this kind of thing (though
they may not be happy about having to do it).
Unfortunately, this bug didn't just appear in git recently, though
it's only been reported recently. It affects upgrades from squeeze.
The triggering change was in dpkg 1.16.1 ("Defer hardlink renames").
So it's probably worth a workaround. Here's some pseudocode to
explain a possible way to do that.
Signed-off-by: Jonathan Nieder <[email protected]>
---
debian/changelog | 6 ++++--
debian/git.preinst | 30 ++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 080286a3..f69995bf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -18,8 +18,10 @@ git (1:1.7.7-2) unstable; urgency=low
* 0018-Makefile-add-a-knob-to-turn-off-hardlinks-...diff: new;
Makefile: add a knob to disable hardlinks within bindir and
gitexecdir.
- * debian/rules: add NO_HARDLINKS=1 to OPTS (thx Bastian Blank;
- closes: #642603).
+ * debian/rules: add NO_HARDLINKS=1 to OPTS (thx Bastian Blank).
+ * debian/git.preinst: if /usr/lib/git-core uses btrfs, convert
+ builtins to symlinks before upgrade from git <= 1:1.7.7-1 (thx
+ Antti Kultanen; closes: #642603).
* debian/rules: do not rely on umask to set contrib permissions.
* update debian/copyright.
* debian/watch, debian/copyright: point to code.google.com for now.
diff --git a/debian/git.preinst b/debian/git.preinst
index f3502d96..8fb7feb6 100644
--- a/debian/git.preinst
+++ b/debian/git.preinst
@@ -24,6 +24,14 @@ rm_conffile () {
fi
}
+is_btrfs () {
+ path=$1
+
+ fs=$(stat -f -c%t "$path")
+ # value from linux/magic.h
+ test "$fs" = 9123683e
+}
+
# Now /etc/emacs/site-start.d/50git-core.el belongs to the
# git-el package. If we are upgrading from a pre- 1.7.4.1-2~
# version then git-el is at most unpacked (so its version
@@ -31,3 +39,25 @@ rm_conffile () {
# an unchanged 50git-core.el file without danger.
#
rm_conffile /etc/emacs/site-start.d/50git-core.el "$1" "$2"
+
+# Git versions before 1.7.7-2 kept about 100 hard links to
+# /usr/lib/git-core/git at /usr/lib/git-core/git-* to support old
+# scripts. Btrfs doesn't like to have more than 128 or so links
+# to a single inode in a given directory. dpkg versions since
+# 1.16.1 temporarily double the number of hard links to an inode
+# when upgrading a package. Boom.
+#
+# Get rid of the hard links before upgrading to avoid trouble.
+if test "$1" = upgrade &&
+ dpkg --compare-versions "$2" lt-nl '1:1.7.7-2' &&
+ is_btrfs /usr/lib/git-core; then
+ refinode=$(stat -c%i /usr/lib/git-core/git)
+ for f in /usr/lib/git-core/*; do
+ test "$f" != /usr/lib/git-core/git || continue
+ inode=$(stat -c%i "$f")
+ test "$inode" = "$refinode" || continue
+ rm -f "$f.dpkg-tmp"
+ ln -s git "$f.dpkg-tmp"
+ mv -f "$f.dpkg-tmp" "$f"
+ done
+fi
--
1.7.7
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]