mirror of
https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git
synced 2025-07-13 11:29:46 +03:00
pmbootstrap status: check if git repo is outdated (!1882)
Use the timestamp of .git/FETCH_HEAD in each git repository, to determine if too much time has passed since the last fetch/pull. Modify pmb.helpers.git.clone, so FETCH_HEAD is always created if it does not exist (because "git clone" would not create it). Related: #1829
This commit is contained in:
parent
c8526f2fcb
commit
cfd93bc6ea
5 changed files with 79 additions and 13 deletions
|
@ -441,6 +441,9 @@ git_repos = {
|
||||||
"pmaports": "https://gitlab.com/postmarketOS/pmaports.git",
|
"pmaports": "https://gitlab.com/postmarketOS/pmaports.git",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# When a git repository is considered outdated (in seconds)
|
||||||
|
# (Measuring timestamp of FETCH_HEAD: https://stackoverflow.com/a/9229377)
|
||||||
|
git_repo_outdated = 3600 * 24 * 2
|
||||||
|
|
||||||
#
|
#
|
||||||
# APORTGEN
|
# APORTGEN
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
|
@ -32,22 +33,25 @@ def clone(args, name_repo, shallow=True):
|
||||||
if name_repo not in pmb.config.git_repos:
|
if name_repo not in pmb.config.git_repos:
|
||||||
raise ValueError("No git repository configured for " + name_repo)
|
raise ValueError("No git repository configured for " + name_repo)
|
||||||
|
|
||||||
# Skip if already checked out
|
|
||||||
path = get_path(args, name_repo)
|
path = get_path(args, name_repo)
|
||||||
if os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
return
|
# Build git command
|
||||||
|
url = pmb.config.git_repos[name_repo]
|
||||||
|
command = ["git", "clone"]
|
||||||
|
if shallow:
|
||||||
|
command += ["--depth=1"]
|
||||||
|
command += [url, path]
|
||||||
|
|
||||||
# Build git command
|
# Create parent dir and clone
|
||||||
url = pmb.config.git_repos[name_repo]
|
logging.info("Clone git repository: " + url)
|
||||||
command = ["git", "clone"]
|
os.makedirs(args.work + "/cache_git", exist_ok=True)
|
||||||
if shallow:
|
pmb.helpers.run.user(args, command, output="stdout")
|
||||||
command += ["--depth=1"]
|
|
||||||
command += [url, path]
|
|
||||||
|
|
||||||
# Create parent dir and clone
|
# FETCH_HEAD does not exist after initial clone. Create it, so
|
||||||
logging.info("Clone git repository: " + url)
|
# is_outdated() can use it.
|
||||||
os.makedirs(args.work + "/cache_git", exist_ok=True)
|
fetch_head = path + "/.git/FETCH_HEAD"
|
||||||
pmb.helpers.run.user(args, command, output="stdout")
|
if not os.path.exists(fetch_head):
|
||||||
|
open(fetch_head, "w").close()
|
||||||
|
|
||||||
|
|
||||||
def rev_parse(args, path, revision="HEAD", extra_args: list = []):
|
def rev_parse(args, path, revision="HEAD", extra_args: list = []):
|
||||||
|
@ -164,3 +168,22 @@ def pull(args, name_repo):
|
||||||
command = ["git", "merge", "--ff-only", branch_upstream]
|
command = ["git", "merge", "--ff-only", branch_upstream]
|
||||||
pmb.helpers.run.user(args, command, path, "stdout")
|
pmb.helpers.run.user(args, command, path, "stdout")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def is_outdated(args, path):
|
||||||
|
# FETCH_HEAD always exists in repositories cloned by pmbootstrap.
|
||||||
|
# Usually it does not (before first git fetch/pull), but there is no good
|
||||||
|
# fallback. For exampe, getting the _creation_ date of .git/HEAD is non-
|
||||||
|
# trivial with python on linux (https://stackoverflow.com/a/39501288).
|
||||||
|
# Note that we have to assume here, that the user had fetched the "origin"
|
||||||
|
# repository. If the user fetched another repository, FETCH_HEAD would also
|
||||||
|
# get updated, even though "origin" may be outdated. For pmbootstrap status
|
||||||
|
# it is good enough, because it should help the users that are not doing
|
||||||
|
# much with pmaports.git to know when it is outdated. People who manually
|
||||||
|
# fetch other repos should usually know that and how to handle that
|
||||||
|
# situation.
|
||||||
|
path_head = path + "/.git/FETCH_HEAD"
|
||||||
|
date_head = os.path.getmtime(path_head)
|
||||||
|
|
||||||
|
date_outdated = time.time() - pmb.config.git_repo_outdated
|
||||||
|
return date_head <= date_outdated
|
||||||
|
|
|
@ -91,6 +91,12 @@ def print_checks_git_repo(args, repo, details=True):
|
||||||
"update with 'pmbootstrap pull'")
|
"update with 'pmbootstrap pull'")
|
||||||
log_ok("up to date with remote branch")
|
log_ok("up to date with remote branch")
|
||||||
|
|
||||||
|
# Outdated remote information
|
||||||
|
if pmb.helpers.git.is_outdated(args, path):
|
||||||
|
return log_nok_ret(-5, "outdated remote information",
|
||||||
|
"update with 'pmbootstrap pull'")
|
||||||
|
log_ok("remote information updated recently (via git fetch/pull)")
|
||||||
|
|
||||||
return (0, "")
|
return (0, "")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
import shutil
|
import shutil
|
||||||
|
import time
|
||||||
|
|
||||||
import pmb_test # noqa
|
import pmb_test # noqa
|
||||||
import pmb_test.git
|
import pmb_test.git
|
||||||
|
@ -146,3 +147,29 @@ def test_pull(args, monkeypatch, tmpdir):
|
||||||
run_git(["reset", "--hard", "origin/master"])
|
run_git(["reset", "--hard", "origin/master"])
|
||||||
run_git(["commit", "--allow-empty", "-m", "new"], "remote")
|
run_git(["commit", "--allow-empty", "-m", "new"], "remote")
|
||||||
assert func(args, name_repo) == 0
|
assert func(args, name_repo) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_outdated(args, tmpdir, monkeypatch):
|
||||||
|
func = pmb.helpers.git.is_outdated
|
||||||
|
|
||||||
|
# Override time.time(): now is "100"
|
||||||
|
def fake_time():
|
||||||
|
return 100.0
|
||||||
|
monkeypatch.setattr(time, "time", fake_time)
|
||||||
|
|
||||||
|
# Create .git/FETCH_HEAD
|
||||||
|
path = str(tmpdir)
|
||||||
|
os.mkdir(path + "/.git")
|
||||||
|
fetch_head = path + "/.git/FETCH_HEAD"
|
||||||
|
open(fetch_head, "w").close()
|
||||||
|
|
||||||
|
# Set mtime to 90
|
||||||
|
os.utime(fetch_head, times=(0, 90))
|
||||||
|
|
||||||
|
# Outdated (date_outdated: 90)
|
||||||
|
monkeypatch.setattr(pmb.config, "git_repo_outdated", 10)
|
||||||
|
assert func(args, path) is True
|
||||||
|
|
||||||
|
# Not outdated (date_outdated: 89)
|
||||||
|
monkeypatch.setattr(pmb.config, "git_repo_outdated", 11)
|
||||||
|
assert func(args, path) is False
|
||||||
|
|
|
@ -83,3 +83,10 @@ def test_print_checks_git_repo(args, monkeypatch, tmpdir):
|
||||||
run_git(["pull"])
|
run_git(["pull"])
|
||||||
status, _ = func(args, name_repo)
|
status, _ = func(args, name_repo)
|
||||||
assert status == 0
|
assert status == 0
|
||||||
|
|
||||||
|
# Outdated remote information
|
||||||
|
def is_outdated(args, path):
|
||||||
|
return True
|
||||||
|
monkeypatch.setattr(pmb.helpers.git, "is_outdated", is_outdated)
|
||||||
|
status, _ = func(args, name_repo)
|
||||||
|
assert status == -5
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue