mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
Install a default pre-auto-gc hook in all repositories
This hook is evaluated by `git gc --auto` to determine if it is a good idea to execute a GC at this time, or defer it to some later date. When working on a laptop its a good idea to avoid GC if you are on battery power as the extra CPU and disk IO would consume a decent amount of the charge. The hook is the standard sample hook from git.git contrib/hooks, last modified in git.git by 84ed4c5d117d72f02cc918e413b9861a9d2846d7. I added the GPLv2 header to the script to ensure the license notice is clear, as it does not match repo's own APLv2 license. We only update hooks during initial repository creation or on a repo sync. This way we don't incur huge overheads from the hook stat operations during "repo status" or even the normal "repo sync" cases. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
438ee1cad9
commit
c9ef744c7b
2
error.py
2
error.py
@ -64,3 +64,5 @@ class RepoChangedException(Exception):
|
||||
repo or manifest repositories. In this special case we must
|
||||
use exec to re-execute repo with the new code and manifest.
|
||||
"""
|
||||
def __init__(self, extra_args=[]):
|
||||
self.extra_args = extra_args
|
||||
|
44
hooks/pre-auto-gc
Executable file
44
hooks/pre-auto-gc
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify if you are on battery, in case you
|
||||
# are running Linux or OS X. Called by git-gc --auto with no arguments.
|
||||
# The hook should exit with non-zero status after issuing an appropriate
|
||||
# message if it wants to stop the auto repacking.
|
||||
|
||||
# This program 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 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
if test -x /sbin/on_ac_power && /sbin/on_ac_power
|
||||
then
|
||||
exit 0
|
||||
elif test "$(cat /sys/class/power_supply/AC/online 2>/dev/null)" = 1
|
||||
then
|
||||
exit 0
|
||||
elif grep -q 'on-line' /proc/acpi/ac_adapter/AC/state 2>/dev/null
|
||||
then
|
||||
exit 0
|
||||
elif grep -q '0x01$' /proc/apm 2>/dev/null
|
||||
then
|
||||
exit 0
|
||||
elif grep -q "AC Power \+: 1" /proc/pmu/info 2>/dev/null
|
||||
then
|
||||
exit 0
|
||||
elif test -x /usr/bin/pmset && /usr/bin/pmset -g batt |
|
||||
grep -q "Currently drawing from 'AC Power'"
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Auto packing deferred; not on AC"
|
||||
exit 1
|
8
main.py
8
main.py
@ -186,11 +186,13 @@ def _Main(argv):
|
||||
repo._Run(argv)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
except RepoChangedException:
|
||||
# If the repo or manifest changed, re-exec ourselves.
|
||||
except RepoChangedException, rce:
|
||||
# If repo changed, re-exec ourselves.
|
||||
#
|
||||
argv = list(sys.argv)
|
||||
argv.extend(rce.extra_args)
|
||||
try:
|
||||
os.execv(__file__, sys.argv)
|
||||
os.execv(__file__, argv)
|
||||
except OSError, e:
|
||||
print >>sys.stderr, 'fatal: cannot restart repo after upgrade'
|
||||
print >>sys.stderr, 'fatal: %s' % e
|
||||
|
68
project.py
68
project.py
@ -46,6 +46,32 @@ def _info(fmt, *args):
|
||||
def not_rev(r):
|
||||
return '^' + r
|
||||
|
||||
|
||||
hook_list = None
|
||||
def repo_hooks():
|
||||
global hook_list
|
||||
if hook_list is None:
|
||||
d = os.path.abspath(os.path.dirname(__file__))
|
||||
d = os.path.join(d , 'hooks')
|
||||
hook_list = map(lambda x: os.path.join(d, x), os.listdir(d))
|
||||
return hook_list
|
||||
|
||||
def relpath(dst, src):
|
||||
src = os.path.dirname(src)
|
||||
top = os.path.commonprefix([dst, src])
|
||||
if top.endswith('/'):
|
||||
top = top[:-1]
|
||||
else:
|
||||
top = os.path.dirname(top)
|
||||
|
||||
tmp = src
|
||||
rel = ''
|
||||
while top != tmp:
|
||||
rel += '../'
|
||||
tmp = os.path.dirname(tmp)
|
||||
return rel + dst[len(top) + 1:]
|
||||
|
||||
|
||||
class DownloadedChange(object):
|
||||
_commit_cache = None
|
||||
|
||||
@ -472,7 +498,10 @@ class Project(object):
|
||||
self._RepairAndroidImportErrors()
|
||||
self._InitMRef()
|
||||
return True
|
||||
|
||||
|
||||
def PostRepoUpgrade(self):
|
||||
self._InitHooks()
|
||||
|
||||
def _CopyFiles(self):
|
||||
for file in self.copyfiles:
|
||||
file._Copy()
|
||||
@ -795,14 +824,29 @@ class Project(object):
|
||||
to_rm = []
|
||||
for old_hook in to_rm:
|
||||
os.remove(os.path.join(hooks, old_hook))
|
||||
|
||||
# TODO(sop) install custom repo hooks
|
||||
self._InitHooks()
|
||||
|
||||
m = self.manifest.manifestProject.config
|
||||
for key in ['user.name', 'user.email']:
|
||||
if m.Has(key, include_defaults = False):
|
||||
self.config.SetString(key, m.GetString(key))
|
||||
|
||||
def _InitHooks(self):
|
||||
hooks = self._gitdir_path('hooks')
|
||||
if not os.path.exists(hooks):
|
||||
os.makedirs(hooks)
|
||||
for stock_hook in repo_hooks():
|
||||
dst = os.path.join(hooks, os.path.basename(stock_hook))
|
||||
try:
|
||||
os.symlink(relpath(stock_hook, dst), dst)
|
||||
except OSError, e:
|
||||
if e.errno == errno.EEXIST:
|
||||
pass
|
||||
elif e.errno == errno.EPERM:
|
||||
raise GitError('filesystem must support symlinks')
|
||||
else:
|
||||
raise
|
||||
|
||||
def _InitRemote(self):
|
||||
if self.remote.fetchUrl:
|
||||
remote = self.GetRemote(self.remote.name)
|
||||
@ -842,19 +886,6 @@ class Project(object):
|
||||
if not os.path.exists(dotgit):
|
||||
os.makedirs(dotgit)
|
||||
|
||||
topdir = os.path.commonprefix([self.gitdir, dotgit])
|
||||
if topdir.endswith('/'):
|
||||
topdir = topdir[:-1]
|
||||
else:
|
||||
topdir = os.path.dirname(topdir)
|
||||
|
||||
tmpdir = dotgit
|
||||
relgit = ''
|
||||
while topdir != tmpdir:
|
||||
relgit += '../'
|
||||
tmpdir = os.path.dirname(tmpdir)
|
||||
relgit += self.gitdir[len(topdir) + 1:]
|
||||
|
||||
for name in ['config',
|
||||
'description',
|
||||
'hooks',
|
||||
@ -866,8 +897,9 @@ class Project(object):
|
||||
'rr-cache',
|
||||
'svn']:
|
||||
try:
|
||||
os.symlink(os.path.join(relgit, name),
|
||||
os.path.join(dotgit, name))
|
||||
src = os.path.join(self.gitdir, name)
|
||||
dst = os.path.join(dotgit, name)
|
||||
os.symlink(relpath(src, dst), dst)
|
||||
except OSError, e:
|
||||
if e.errno == errno.EPERM:
|
||||
raise GitError('filesystem must support symlinks')
|
||||
|
@ -49,6 +49,9 @@ the manifest.
|
||||
p.add_option('--no-repo-verify',
|
||||
dest='no_repo_verify', action='store_true',
|
||||
help='do not verify repo source code')
|
||||
p.add_option('--repo-upgraded',
|
||||
dest='repo_upgraded', action='store_true',
|
||||
help='perform additional actions after a repo upgrade')
|
||||
|
||||
def _Fetch(self, *projects):
|
||||
fetched = set()
|
||||
@ -67,6 +70,11 @@ the manifest.
|
||||
mp = self.manifest.manifestProject
|
||||
mp.PreSync()
|
||||
|
||||
if opt.repo_upgraded:
|
||||
for project in self.manifest.projects.values():
|
||||
if project.Exists:
|
||||
project.PostRepoUpgrade()
|
||||
|
||||
all = self.GetProjects(args, missing_ok=True)
|
||||
fetched = self._Fetch(rp, mp, *all)
|
||||
|
||||
@ -77,7 +85,7 @@ the manifest.
|
||||
if not rp.Sync_LocalHalf():
|
||||
sys.exit(1)
|
||||
print >>sys.stderr, 'info: Restarting repo with latest version'
|
||||
raise RepoChangedException()
|
||||
raise RepoChangedException(['--repo-upgraded'])
|
||||
else:
|
||||
print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user