66a63d37387ac3786ca68984ed0002ecb379086b
[apex.git] / apex / build_utils.py
1 ##############################################################################
2 # Copyright (c) 2017 Feng Pan (fpan@redhat.com) and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import argparse
11 import git
12 import logging
13 import os
14 from pygerrit2.rest import GerritRestAPI
15 import re
16 import shutil
17 import sys
18
19 from urllib.parse import quote_plus
20
21
22 def clone_fork(args):
23     ref = None
24     logging.info("Cloning {}".format(args.repo))
25
26     try:
27         cm = git.Repo(search_parent_directories=True).commit().message
28     except git.exc.InvalidGitRepositoryError:
29         logging.debug('Current Apex directory is not a git repo: {}'
30                       .format(os.getcwd()))
31         cm = ''
32
33     logging.info("Current commit message: {}".format(cm))
34     m = re.search('{}:\s*(\S+)'.format(args.repo), cm)
35
36     if m:
37         change_id = m.group(1)
38         logging.info("Using change ID {} from {}".format(change_id, args.repo))
39         rest = GerritRestAPI(url=args.url)
40         change_path = "{}~{}~{}".format(args.repo, quote_plus(args.branch),
41                                         change_id)
42         change_str = "changes/{}?o=CURRENT_REVISION".format(change_path)
43         change = rest.get(change_str)
44         try:
45             assert change['status'] not in 'ABANDONED' 'CLOSED',\
46                 'Change {} is in {} state'.format(change_id, change['status'])
47             if change['status'] == 'MERGED':
48                 logging.info('Change {} is merged, ignoring...'
49                              .format(change_id))
50             else:
51                 current_revision = change['current_revision']
52                 ref = change['revisions'][current_revision]['ref']
53                 logging.info('setting ref to {}'.format(ref))
54         except KeyError:
55             logging.error('Failed to get valid change data structure from url '
56                           '{}/{}, data returned: \n{}'
57                           .format(change_id, change_str, change))
58             raise
59
60     # remove existing file or directory named repo
61     if os.path.exists(args.repo):
62         if os.path.isdir(args.repo):
63             shutil.rmtree(args.repo)
64         else:
65             os.remove(args.repo)
66
67     ws = git.Repo.clone_from("{}/{}".format(args.url, args.repo),
68                              args.repo, b=args.branch)
69     if ref:
70         git_cmd = ws.git
71         git_cmd.fetch("{}/{}".format(args.url, args.repo), ref)
72         git_cmd.checkout('FETCH_HEAD')
73         logging.info('Checked out commit:\n{}'.format(ws.head.commit.message))
74
75
76 def get_parser():
77     parser = argparse.ArgumentParser()
78     parser.add_argument('--debug', action='store_true', default=False,
79                         help="Turn on debug messages")
80     subparsers = parser.add_subparsers()
81     fork = subparsers.add_parser('clone-fork',
82                                  help='Clone fork of dependent repo')
83     fork.add_argument('-r', '--repo', required=True, help='Name of repository')
84     fork.add_argument('-u', '--url',
85                       default='https://gerrit.opnfv.org/gerrit',
86                       help='Gerrit URL of repository')
87     fork.add_argument('-b', '--branch',
88                       default='master',
89                       help='Branch to checkout')
90     fork.set_defaults(func=clone_fork)
91     return parser
92
93
94 def main():
95     parser = get_parser()
96     args = parser.parse_args(sys.argv[1:])
97     if args.debug:
98         logging_level = logging.DEBUG
99     else:
100         logging_level = logging.INFO
101
102     logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s',
103                         datefmt='%m/%d/%Y %I:%M:%S %p',
104                         level=logging_level)
105     if hasattr(args, 'func'):
106         args.func(args)
107     else:
108         parser.print_help()
109         exit(1)
110
111
112 if __name__ == "__main__":
113     main()