| 1 | import pytest |
| 2 | import os |
| 3 | import yaml |
| 4 | import logging |
| 5 | import hashlib |
| 6 | |
| 7 | from git import Repo |
| 8 | |
| 9 | import settings as Settings |
| 10 | |
| 11 | def is_ref_branch(repo, ref): |
| 12 | try: |
| 13 | repo.remote().refs[ref] |
| 14 | is_branch = True |
| 15 | except: |
| 16 | is_branch = False |
| 17 | |
| 18 | return is_branch |
| 19 | |
| 20 | |
| 21 | def is_ref_tag(repo, ref): |
| 22 | try: |
| 23 | repo.tags[ref] |
| 24 | is_tag = True |
| 25 | except: |
| 26 | is_tag = False |
| 27 | |
| 28 | return is_tag |
| 29 | |
| 30 | |
| 31 | def is_ref_commit(repo, ref): |
| 32 | try: |
| 33 | Repo.rev_parse(repo, ref) |
| 34 | is_commit = True |
| 35 | except: |
| 36 | is_commit = False |
| 37 | |
| 38 | return is_commit |
| 39 | |
| 40 | |
| 41 | def logging_setup(): |
| 42 | logger_format = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' |
| 43 | logging.basicConfig(level=logging.DEBUG, |
| 44 | format=logger_format, |
| 45 | datefmt='%m-%d %H:%M', |
| 46 | filename='./debug.log', |
| 47 | filemode='w') |
| 48 | # define a Handler which writes INFO messages or higher to the sys.stderr |
| 49 | console = logging.StreamHandler() |
| 50 | console.setLevel(logging.DEBUG) |
| 51 | # set a format which is simpler for console use |
| 52 | formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') |
| 53 | # tell the handler to use this format |
| 54 | console.setFormatter(formatter) |
| 55 | # add the handler to the root logger |
| 56 | logging.getLogger('').addHandler(console) |
| 57 | |
| 58 | |
| 59 | logging_setup() |
| 60 | |
| 61 | # Remote setup |
| 62 | logger_git = logging.getLogger('setup.git') |
| 63 | |
| 64 | # Fetch local base repository |
| 65 | with open(Settings.configuration_file, 'r') as stream: |
| 66 | config = yaml.load(stream) |
| 67 | |
| 68 | # Validate that all default dependancy are present. |
| 69 | # TODO: move to function |
| 70 | projects_markers = set() |
| 71 | for project, markers in config.items(): |
| 72 | if markers is None: |
| 73 | continue |
| 74 | for marker in markers: |
| 75 | projects_markers.add(marker['marker']) |
| 76 | |
| 77 | for project, markers in config.items(): |
| 78 | if markers is None: |
| 79 | continue |
| 80 | for marker in markers: |
| 81 | if 'precook_deps' in marker: |
| 82 | for dep in marker['precook_deps']: |
| 83 | if dep not in projects_markers: |
| 84 | raise Exception("{} is not defined".format(dep)) |
| 85 | |
| 86 | |
| 87 | # Retrieve all possibles remotes and clean url for path |
| 88 | remotes = {} |
| 89 | for project, markers in config.items(): |
| 90 | if markers is None: |
| 91 | continue |
| 92 | for marker in markers: |
| 93 | url = marker['url'] |
| 94 | url2path = hashlib.sha1(url.encode('utf8')).hexdigest() |
| 95 | path = os.path.abspath(Settings.git_remote_folder + '/' + url2path) |
| 96 | remotes[url] = path |
| 97 | |
| 98 | logger_git.info('Remotes to be fetched {}'.format(remotes)) |
| 99 | |
| 100 | if not os.path.isdir(Settings.git_remote_folder): |
| 101 | os.makedirs(Settings.git_remote_folder) |
| 102 | |
| 103 | # Fetch the remote |
| 104 | for url, path in remotes.items(): |
| 105 | if os.path.exists(path): |
| 106 | if not os.path.isdir(path): |
| 107 | logger_git.error('Remote path {} exists and is not a folder'.format(path)) |
| 108 | exit() |
| 109 | repo = Repo(path) |
| 110 | else: |
| 111 | repo = Repo.clone_from(url, path) |
| 112 | |
| 113 | # TODO: might be necessary to actually update the base branch, to validate |
| 114 | repo.remote().fetch() |
| 115 | |
| 116 | # Create marker definition for test runners |
| 117 | runnable_markers = {} |
| 118 | for project, markers in config.items(): |
| 119 | if markers is None: |
| 120 | continue |
| 121 | for marker in markers: |
| 122 | name = marker['marker'] |
| 123 | ref = marker['ref'] |
| 124 | url = marker['url'] |
| 125 | if 'precook_deps' in marker: |
| 126 | deps = marker['precook_deps'] |
| 127 | else: |
| 128 | deps = [] |
| 129 | |
| 130 | path = remotes[url] |
| 131 | repo = Repo(path) |
| 132 | |
| 133 | git_object = None |
| 134 | if is_ref_branch(repo, ref): |
| 135 | git_object = Repo.rev_parse(repo, repo.remote().refs[ref].name) |
| 136 | elif is_ref_tag(repo, ref): |
| 137 | git_object = repo.tags[ref].commit |
| 138 | elif is_ref_commit(repo, ref): |
| 139 | git_object = repo.commit(ref) |
| 140 | |
| 141 | if git_object is None: |
| 142 | logger_git.error('Invalid git reference for marker "{}"'.format(name)) |
| 143 | exit(1) |
| 144 | |
| 145 | logger_git.info('Marker:{: <30} Sha1 {: <20}'.format(name, git_object.hexsha)) |
| 146 | |
| 147 | if name in runnable_markers: |
| 148 | logger_git.error('Duplicate for entry for marker "{}"'.format(name)) |
| 149 | exit(1) |
| 150 | |
| 151 | runnable_markers[name] = { |
| 152 | 'project': project, |
| 153 | 'sha1': git_object.hexsha, |
| 154 | 'url': url, |
| 155 | 'path': path, |
| 156 | 'deps': deps |
| 157 | } |
| 158 | |
| 159 | with open(Settings.run_configuration_file, 'w') as run_configuration: |
| 160 | yaml.dump(runnable_markers, run_configuration, default_flow_style=False) |