- fields = info['table'][resource]
- v.status('Fetching resource "%s"' % resource)
- url = urllib.parse.urljoin(info['forwarded_url'], fields['url'])
- request = urllib.request.urlopen(url, timeout=10)
- if fields['size'] < 4096:
- fields['content'] = request.read()
- else:
- with tempfile.NamedTemporaryFile(suffix='.nixexprs.tar.xz', delete=False) as tmp_file:
- shutil.copyfileobj(request, tmp_file)
- fields['file'] = tmp_file.name
- v.result(request.status == 200)
- v.status('Verifying digest for "%s"' % resource)
- if fields['size'] < 4096:
- actual_hash = hashlib.sha256(fields['content']).hexdigest()
- else:
- hasher = hashlib.sha256()
- with open(fields['file'], 'rb') as f:
- # pylint: disable=cell-var-from-loop
- for block in iter(lambda: f.read(4096), b''):
- hasher.update(block)
- actual_hash = hasher.hexdigest()
- v.result(actual_hash == fields['digest'])
- v.check('Verifying git commit on main page matches git commit in table',
- info['table']['git-revision']['content'].decode() == info['git_commit'])
-
-
-def extract_channel(v: Verification, info: Dict[str, Any]) -> None:
- with tempfile.TemporaryDirectory() as d:
- v.status('Extracting nixexprs.tar.xz')
- shutil.unpack_archive(info['table']['nixexprs.tar.xz']['file'], d)
+ fields = channel.table[resource]
+ url = urllib.parse.urljoin(channel.forwarded_url, fields.url)
+ fields.file = fetch_with_nix_prefetch_url(v, url, fields.digest)
+ v.status('Verifying git commit on main page matches git commit in table')
+ v.result(
+ open(
+ channel.table['git-revision'].file).read(999) == channel.git_commit)
+
+
+def git_fetch(v: Verification, channel: Channel) -> None:
+ # It would be nice if we could share the nix git cache, but as of the time
+ # of writing it is transitioning from gitv2 (deprecated) to gitv3 (not ready
+ # yet), and trying to straddle them both is too far into nix implementation
+ # details for my comfort. So we re-implement here half of nix.fetchGit.
+ # :(
+
+ # TODO: Consider using pyxdg to find this path.
+ channel.git_cachedir = os.path.expanduser(
+ '~/.cache/nix-pin-channel/git/%s' %
+ digest_string(
+ channel.url.encode()))
+ if not os.path.exists(channel.git_cachedir):
+ v.status("Initializing git repo")
+ process = subprocess.run(
+ ['git', 'init', '--bare', channel.git_cachedir])
+ v.result(process.returncode == 0)
+
+ v.status('Checking if we already have this rev:')
+ process = subprocess.run(
+ ['git', '-C', channel.git_cachedir, 'cat-file', '-e', channel.git_commit])
+ if process.returncode == 0:
+ v.status('yes')
+ if process.returncode == 1:
+ v.status('no')
+ v.result(process.returncode == 0 or process.returncode == 1)
+ if process.returncode == 1:
+ v.status('Fetching ref "%s"' % channel.git_ref)
+ # We don't use --force here because we want to abort and freak out if forced
+ # updates are happening.
+ process = subprocess.run(['git',
+ '-C',
+ channel.git_cachedir,
+ 'fetch',
+ channel.git_repo,
+ '%s:%s' % (channel.git_ref,
+ channel.git_ref)])
+ v.result(process.returncode == 0)
+ v.status('Verifying that fetch retrieved this rev')
+ process = subprocess.run(
+ ['git', '-C', channel.git_cachedir, 'cat-file', '-e', channel.git_commit])
+ v.result(process.returncode == 0)
+
+ v.status('Verifying rev is an ancestor of ref')
+ process = subprocess.run(['git',
+ '-C',
+ channel.git_cachedir,
+ 'merge-base',
+ '--is-ancestor',
+ channel.git_commit,
+ channel.git_ref])
+ v.result(process.returncode == 0)
+
+
+def check_channel_contents(v: Verification, channel: Channel) -> None:
+ with tempfile.TemporaryDirectory() as channel_contents, \
+ tempfile.TemporaryDirectory() as git_contents:
+ v.status('Extracting tarball %s' %
+ channel.table['nixexprs.tar.xz'].file)
+ shutil.unpack_archive(
+ channel.table['nixexprs.tar.xz'].file,
+ channel_contents)
+ v.ok()
+ v.status('Checking out corresponding git revision')
+ git = subprocess.Popen(['git',
+ '-C',
+ channel.git_cachedir,
+ 'archive',
+ channel.git_commit],
+ stdout=subprocess.PIPE)
+ tar = subprocess.Popen(
+ ['tar', 'x', '-C', git_contents, '-f', '-'], stdin=git.stdout)
+ git.stdout.close()
+ tar.wait()
+ git.wait()
+ v.result(git.returncode == 0 and tar.returncode == 0)
+ v.status('Comparing channel tarball with git checkout')
+ match, mismatch, errors = compare(os.path.join(
+ channel_contents, channel.release_name), git_contents)