3 # Copyright 2017 The Glslang Authors. All rights reserved.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Get source files for Glslang and its dependencies from public repositories.
26 KNOWN_GOOD_FILE
= 'known_good.json'
28 SITE_TO_KNOWN_GOOD_FILE
= { 'github' : 'known_good.json',
29 'gitlab' : 'known_good_khr.json' }
31 # Maps a site name to its hostname.
32 SITE_TO_HOST
= { 'github' : 'https://github.com/',
33 'gitlab' : 'git@gitlab.khronos.org:' }
38 def command_output(cmd
, directory
, fail_ok
=False):
39 """Runs a command in a directory and returns its standard output stream.
41 Captures the standard error stream.
43 Raises a RuntimeError if the command fails to launch or otherwise fails.
46 print('In {d}: {cmd}'.format(d
=directory
, cmd
=cmd
))
47 p
= subprocess
.Popen(cmd
,
49 stdout
=subprocess
.PIPE
)
50 (stdout
, _
) = p
.communicate()
51 if p
.returncode
!= 0 and not fail_ok
:
52 raise RuntimeError('Failed to run {} in {}'.format(cmd
, directory
))
58 def command_retval(cmd
, directory
):
59 """Runs a command in a directory and returns its return value.
61 Captures the standard error stream.
63 p
= subprocess
.Popen(cmd
,
65 stdout
=subprocess
.PIPE
)
70 class GoodCommit(object):
71 """Represents a good commit for a repository."""
73 def __init__(self
, json
):
74 """Initializes this good commit object.
77 'json': A fully populated JSON object describing the commit.
80 self
.name
= json
['name']
81 self
.site
= json
['site']
82 self
.subrepo
= json
['subrepo']
83 self
.subdir
= json
['subdir'] if ('subdir' in json
) else '.'
84 self
.commit
= json
['commit']
87 """Returns the URL for the repository."""
88 host
= SITE_TO_HOST
[self
.site
]
89 return '{host}{subrepo}'.format(
94 """Add the remote 'known-good' if it does not exist."""
95 remotes
= command_output(['git', 'remote'], self
.subdir
).splitlines()
96 if b
'known-good' not in remotes
:
97 command_output(['git', 'remote', 'add', 'known-good', self
.GetUrl()], self
.subdir
)
100 """Check if the repository contains the known-good commit."""
101 return 0 == subprocess
.call(['git', 'rev-parse', '--verify', '--quiet',
102 self
.commit
+ "^{commit}"],
106 os
.makedirs(self
.subdir
, exist_ok
=True)
107 command_output(['git', 'clone', self
.GetUrl(), '.'], self
.subdir
)
110 command_output(['git', 'fetch', 'known-good'], self
.subdir
)
113 if not os
.path
.exists(os
.path
.join(self
.subdir
,'.git')):
116 if not self
.HasCommit():
118 command_output(['git', 'checkout', self
.commit
], self
.subdir
)
121 def GetGoodCommits(site
):
122 """Returns the latest list of GoodCommit objects."""
123 known_good_file
= SITE_TO_KNOWN_GOOD_FILE
[site
]
124 with
open(known_good_file
) as known_good
:
125 return [GoodCommit(c
) for c
in json
.loads(known_good
.read())['commits']]
129 parser
= argparse
.ArgumentParser(description
='Get Glslang source dependencies at a known-good commit')
130 parser
.add_argument('--dir', dest
='dir', default
='.',
131 help="Set target directory for Glslang source root. Default is \'.\'.")
132 parser
.add_argument('--site', dest
='site', default
='github',
133 help="Set git server site. Default is github.")
135 args
= parser
.parse_args()
137 commits
= GetGoodCommits(args
.site
)
139 os
.makedirs(args
.dir, exist_ok
=True)
140 print('Change directory to {d}'.format(d
=args
.dir))
143 # Create the subdirectories in sorted order so that parent git repositories
145 for c
in sorted(commits
, key
=lambda x
: x
.subdir
):
146 print('Get {n}\n'.format(n
=c
.name
))
151 if __name__
== '__main__':