Re: "dpkg-git update" and "dpkg-git commit"
On Sun, 28 Oct 2007, Helge Kreutzmann wrote:
> > We have no way to filter anything on the server side. But maybe we can
> > provide you some scripts that hide the git commands behind two scripts
> > like "dpkg-git update" and "dpkg-git commit" (which would have the
> > same logic as SVN).
> I like the idea quite a bit and thus would be enlightend if something
> like this could be implemented and distributed. This would also allow
> you to update the actual git commands without anyone noticing :-))
I had a try to create such a command. It's attached to this mail. It
requires git 1.5.3 as "git-stash" is used.
It tries to mimic the behaviour of svn. Put the script in your dpkg
repository and call it from the root of the repository.
There are two important commands only:
./dpkg-vcs update
./dpkg-vcs commit
The output of the script itself is prefixed with "**" so that you can
easily skip git's own output (in case you don't understand it). The
script does a fair number of verifications and checks the exit code of
several important git command and gives you proper indication on how
to continue.
Please try it and feel free to give some feedback.
Cheers,
--
Raphaël Hertzog
Premier livre français sur Debian GNU/Linux :
http://www.ouaza.com/livre/admin-debian/
#!/bin/sh
#Â Copyright 2007 Raphael Hertzog <hertzog@debian.org>
#
# This program is free software; you may redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This 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.
#
# A copy of the GNU General Public License is available as
# /usr/share/common-licenses/GPL in the Debian GNU/Linux distribution
# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html.
# You can also obtain it by writing to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
# This script is only meant to be used in the master branch of dpkg
# This branch is created by default by a git clone
# ssh://git.debian.org/git/dpkg/dpkg.git
# Git 1.5.3 is required (for git-stash)
has_changes_in_index() {
# git-diff --quiet returns 1 when there are changes
if git diff --quiet --cached; then
return 1
else
return 0
fi
}
has_changes_in_working_tree() {
# git-diff --quiet returns 1 when there are changes
if git diff --quiet; then
return 1
else
return 0
fi
}
is_uptodate() {
unmerged=`git rev-list origin/master ^HEAD`
if test -z "$unmerged"; then
return 0
else
return 1
fi
}
has_unpushed_commits() {
unpushed=`git rev-list HEAD ^origin/master`
if test -n "$unpushed"; then
return 0
else
return 1
fi
}
test -d .git || {
echo "This script must be called from the root of dpkg's git repository." >&2
exit
}
branch=`git-name-rev --name-only HEAD`
[ "$branch" = "master" ] || {
echo "This script must be called from dpkg's master branch." >&2
echo "Call 'git checkout master'."
exit
}
case $1 in
update)
git fetch --quiet origin
if has_unpushed_commits; then
echo "** You have local commits that were not pushed to the remote repository."
if is_uptodate; then
echo "** They are still OK to be pushed."
else
echo "** The remote repository has evolved. Rebasing your work."
$0 rebase
fi
else
if ! is_uptodate; then
echo "** The remote repository has changed. Trying to update."
if has_changes_in_index || has_changes_in_working_tree; then
git merge origin/master
result=$?
if [ $result -eq 0 ]; then
echo "** The repository has been updated."
elif [ $result -eq 1 ]; then
echo "** The repository has been updated but there have been conflicts:"
git ls-files --unmerged | awk '{print $4}' | uniq -c
else
echo "** The automatic merge failed. Try another stratrgy."
echo "** Pushing local changes aside with git stash"
git stash save "WIP saved by dpkg-vcs"
echo "** Merging remote changes, should result in fast-forward"
git merge origin/master
echo "** Reapplying local changes with git stash apply"
git stash apply
result=$?
if [ $result -eq 0 ]; then
echo "** Local changes have been merged"
elif [ $result -eq 1 ]; then
echo "** Local changes have been merged but there have been conflicts:"
git ls-files --unmerged | awk '{print $4}' | uniq -c
else
echo "** git stash apply failed badly and returned $result."
echo "** You're on your own..."
exit 2
fi
fi
fi
else
echo "** Nothing updated, the remote respository hasn't changed."
fi
fi
;;
commit)
git fetch --quiet origin
if ! is_uptodate; then
echo "** You're not up-to-date, please do '$0 update' first."
exit 1
fi
if has_changes_in_index || has_changes_in_working_tree; then
echo "** Committing changes locally"
git commit -a || {
echo "** git commit failed, stopping here."
exit 1
}
fi
if has_unpushed_commits; then
echo "** Pushing your changes to the remote repository"
echo "Here's a resume of what you're going to push:"
git rev-list --pretty=oneline --abbrev-commit master ^origin/master
echo "** Do you confirm that you want to push? [Yn] "
read answer
if [ "$answer" = "" ] || [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
echo "** Calling 'git push'"
git push
fi
fi
;;
rebase)
git fetch --quiet origin
if [ -z "$2" ]; then
echo "** Starting a rebase process..."
git rebase origin/master
result=$?
else
if [ "$2" = "--continue" ] || [ "$2" = "--skip" ]; then
if [ "$2" = "--continue" ]; then
for file in `git ls-files --unmerged | awk '{print $4}' | uniq`; do
git add $file
done
fi
git rebase $2
result=$?
else
echo "Invalid option for '$0 rebase': $2" >&2
exit 1
fi
fi
if [ $result -eq 0 ]; then
echo "** The rebase process is finished. Your repository is up-to-date."
exit 0
elif [ $result -eq 1 ]; then
echo "** Rebase process interrupted by conflicts."
echo "** Edit the files below and fix all the conflicts,"
echo "** then call '$0 rebase --continue':"
git ls-files --unmerged | awk '{print $4}' | uniq -c
exit 1
else
echo "** The rebase process miserably failed for an unknown reason."
echo "** Aborting it."
git rebase --abort
exit 2
fi
;;
*)
echo "$0: invalid syntax" >&2
echo "$0 update: update the master branch of the repository" >&2
echo "$0 commit: commit and push the changes to the master repository" >&2
;;
esac
Reply to: