Coverage for dak/export_suite.py: 30%
50 statements
« prev ^ index » next coverage.py v7.6.0, created at 2026-08-03 16:46 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2026-08-03 16:46 +0000
1# Copyright (C) 2012, Ansgar Burchardt <ansgar@debian.org>
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License along
14# with this program; if not, write to the Free Software Foundation, Inc.,
15# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17import os
18import sys
20import apt_pkg
21from sqlalchemy import select
23from daklib.config import Config
24from daklib.dbconn import ArchiveFile, DBConn, Suite
25from daklib.fstransactions import FilesystemTransaction
28def usage():
29 print(
30 """Usage: dak export-suite -s <suite> [options]
32Export binaries and sources from a suite to a flat directory structure.
34 -c --copy copy files instead of symlinking them
35 -d <directory> target directory to export packages to
36 default: current directory
37 -r --relative use symlinks relative to target directory
38 -s <suite> suite to grab uploads from
39"""
40 )
43def main(argv=None):
44 if argv is None: 44 ↛ 47line 44 didn't jump to line 47
45 argv = sys.argv
47 arguments = [
48 ("h", "help", "Export::Options::Help"),
49 ("c", "copy", "Export::Options::Copy"),
50 ("d", "directory", "Export::Options::Directory", "HasArg"),
51 ("r", "relative", "Export::Options::Relative"),
52 ("s", "suite", "Export::Options::Suite", "HasArg"),
53 ]
55 cnf = Config()
56 apt_pkg.parse_commandline(cnf.Cnf, arguments, argv) # type: ignore[attr-defined]
57 options = cnf.subtree("Export::Options")
59 if "Help" in options or "Suite" not in options: 59 ↛ 63line 59 didn't jump to line 63 because the condition on line 59 was always true
60 usage()
61 sys.exit(0)
63 session = DBConn().session()
65 suite = session.scalars(
66 select(Suite).filter_by(suite_name=options["Suite"]).limit(1)
67 ).first()
68 if suite is None:
69 print("Unknown suite '{0}'".format(options["Suite"]))
70 sys.exit(1)
72 directory = options.get("Directory")
73 if not directory:
74 print("No target directory.")
75 sys.exit(1)
77 symlink = "Copy" not in options
78 relative = "Relative" in options
80 if relative and not symlink:
81 print("E: --relative and --copy cannot be used together.")
82 sys.exit(1)
84 binaries = suite.binaries
85 sources = suite.sources
87 files = []
88 files.extend([b.poolfile for b in binaries])
89 for s in sources:
90 files.extend([ds.poolfile for ds in s.srcfiles])
92 with FilesystemTransaction() as fs:
93 for f in files:
94 af = session.scalars(
95 select(ArchiveFile)
96 .join(ArchiveFile.component)
97 .join(ArchiveFile.file)
98 .where(ArchiveFile.archive == suite.archive)
99 .where(ArchiveFile.file == f)
100 .limit(1)
101 ).first()
102 assert af is not None
103 src = af.path
104 if relative:
105 src = os.path.relpath(src, directory)
106 dst = os.path.join(directory, f.basename)
107 if not os.path.exists(dst):
108 fs.copy(src, dst, symlink=symlink)
109 fs.commit()