1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#!/usr/bin/env python
# Copyright 2010-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
import argparse
import io
import os
import sys
import textwrap
from urllib.parse import urlparse
from os import path as osp
if osp.isfile(
osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")
):
sys.path.insert(
0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")
)
import portage
portage._internal_caller = True
def parse_args(argv):
prog_name = os.path.basename(argv[0])
usage = (
prog_name
+ " [options] "
+ "<src_pkg_dir> <snapshot_dir> <snapshot_uri> <binhost_dir>"
)
prog_desc = (
"This program will copy src_pkg_dir to snapshot_dir "
+ "and inside binhost_dir it will create a Packages index file "
+ "which refers to snapshot_uri. This is intended to solve race "
+ "conditions on binhosts as described at http://crosbug.com/3225."
)
usage += "\n\n"
for line in textwrap.wrap(prog_desc, 70):
usage += line + "\n"
usage += "\n"
usage += "Required Arguments:\n\n"
usage += " src_pkg_dir - the source ${PKGDIR}\n"
usage += " snapshot_dir - destination snapshot " + "directory (must not exist)\n"
usage += (
" snapshot_uri - URI which refers to "
+ "snapshot_dir from the\n"
+ " client side\n"
)
usage += (
" binhost_dir - directory in which to "
+ "write Packages index with\n"
+ " snapshot_uri"
)
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument(
"--hardlinks",
help="create hardlinks (y or n, default is y)",
choices=("y", "n"),
default="y",
)
options, args = parser.parse_known_args(argv[1:])
if len(args) != 4:
parser.error("Required 4 arguments, got %d" % (len(args),))
return parser, options, args
def main(argv):
parser, options, args = parse_args(argv)
src_pkg_dir, snapshot_dir, snapshot_uri, binhost_dir = args
src_pkgs_index = os.path.join(src_pkg_dir, "Packages")
if not os.path.isdir(src_pkg_dir):
parser.error("src_pkg_dir is not a directory: '%s'" % (src_pkg_dir,))
if not os.path.isfile(src_pkgs_index):
parser.error(
"src_pkg_dir does not contain a "
+ "'Packages' index: '%s'" % (src_pkg_dir,)
)
parse_result = urlparse(snapshot_uri)
if not (parse_result.scheme and parse_result.netloc and parse_result.path):
parser.error("snapshot_uri is not a valid URI: '%s'" % (snapshot_uri,))
if os.path.isdir(snapshot_dir):
parser.error("snapshot_dir already exists: '%s'" % snapshot_dir)
try:
os.makedirs(os.path.dirname(snapshot_dir))
except OSError:
pass
if not os.path.isdir(os.path.dirname(snapshot_dir)):
parser.error(
"snapshot_dir parent could not be created: '%s'"
% os.path.dirname(snapshot_dir)
)
try:
os.makedirs(binhost_dir)
except OSError:
pass
if not os.path.isdir(binhost_dir):
parser.error("binhost_dir could not be created: '%s'" % binhost_dir)
cp_opts = "RP"
if options.hardlinks == "n":
cp_opts += "p"
else:
cp_opts += "l"
cp_cmd = "cp -%s %s %s" % (
cp_opts,
portage._shell_quote(src_pkg_dir),
portage._shell_quote(snapshot_dir),
)
ret = os.system(cp_cmd)
if not (os.WIFEXITED(ret) and os.WEXITSTATUS(ret) == os.EX_OK):
return 1
infile = io.open(
portage._unicode_encode(
src_pkgs_index, encoding=portage._encodings["fs"], errors="strict"
),
mode="r",
encoding=portage._encodings["repo.content"],
errors="strict",
)
outfile = portage.util.atomic_ofstream(
os.path.join(binhost_dir, "Packages"),
encoding=portage._encodings["repo.content"],
errors="strict",
)
for line in infile:
if line[:4] == "URI:":
# skip existing URI line
pass
else:
if not line.strip():
# end of header
outfile.write("URI: %s\n\n" % snapshot_uri)
break
outfile.write(line)
for line in infile:
outfile.write(line)
infile.close()
outfile.close()
return os.EX_OK
if __name__ == "__main__":
sys.exit(main(sys.argv))
|