diff --git a/tools/repo_pull/gerrit.py b/tools/repo_pull/gerrit.py index aeaba79c8..e74b90779 100755 --- a/tools/repo_pull/gerrit.py +++ b/tools/repo_pull/gerrit.py @@ -171,13 +171,31 @@ def _decode_xssi_json(data): return json.loads(data) -def query_change_lists(url_opener, gerrit, query_string, limits): - """Query change lists.""" +def _query_change_lists(url_opener, gerrit, query_string, start, count): + """Query change lists from the Gerrit server with a single request. + + This function performs a single query of the Gerrit server based on the + input parameters for a list of changes. The server may return less than + the number of changes requested. The caller should check the last record + returned for the _more_changes attribute to determine if more changes are + available and perform additional queries adjusting the start index. + + Args: + url_opener: URL opener for request + gerrit: Gerrit server URL + query_string: Gerrit query string to select changes + start: Number of changes to be skipped from the beginning + count: Maximum number of changes to return + + Returns: + List of changes + """ data = [ ('q', query_string), ('o', 'CURRENT_REVISION'), ('o', 'CURRENT_COMMIT'), - ('n', str(limits)), + ('start', str(start)), + ('n', str(count)), ] url = gerrit + '/a/changes/?' + urlencode(data) @@ -187,6 +205,40 @@ def query_change_lists(url_opener, gerrit, query_string, limits): finally: response_file.close() +def query_change_lists(url_opener, gerrit, query_string, start, count): + """Query change lists from the Gerrit server. + + This function queries the Gerrit server based on the input parameters for a + list of changes. This function handles querying the server multiple times + if necessary and combining the results that are returned to the caller. + + Args: + url_opener: URL opener for request + gerrit: Gerrit server URL + query_string: Gerrit query string to select changes + start: Number of changes to be skipped from the beginning + count: Maximum number of changes to return + + Returns: + List of changes + """ + changes = [] + while len(changes) < count: + chunk = _query_change_lists(url_opener, gerrit, query_string, + start + len(changes), count - len(changes)) + if not chunk: + break + + changes += chunk + + # The last change object contains a _more_changes attribute if the + # number of changes exceeds the query parameter or the internal server + # limit. Stop iteration if `_more_changes` attribute doesn't exist. + if '_more_changes' not in chunk[-1]: + break + + return changes + def _make_json_post_request(url_opener, url, data, method='POST'): """Open an URL request and decode its response. @@ -361,8 +413,13 @@ def _parse_args(): parser.add_argument('--gitcookies', default=os.path.expanduser('~/.gitcookies'), help='Gerrit cookie file') - parser.add_argument('--limits', default=1000, + parser.add_argument('--limits', default=1000, type=int, help='Max number of change lists') + parser.add_argument('--start', default=0, type=int, + help='Skip first N changes in query') + parser.add_argument('--format', default='json', + choices=['json', 'oneline'], + help='Print format') return parser.parse_args() @@ -383,11 +440,23 @@ def main(): # Query change lists url_opener = create_url_opener_from_args(args) change_lists = query_change_lists( - url_opener, args.gerrit, args.query, args.limits) + url_opener, args.gerrit, args.query, args.start, args.limits) # Print the result - json.dump(change_lists, sys.stdout, indent=4, separators=(', ', ': ')) - print() # Print the end-of-line + if args.format == 'json': + json.dump(change_lists, sys.stdout, indent=4, separators=(', ', ': ')) + print() # Print the end-of-line + elif args.format == 'oneline': + for i, change in enumerate(change_lists): + print('{i:<8} {number:<16} {status:<20} ' \ + '{change_id:<60} {project:<120} ' \ + '{subject}'.format(i=i, + project=change['project'], + change_id=change['change_id'], + status=change['status'], + number=change['_number'], + subject=change['subject'])) + if __name__ == '__main__': main() diff --git a/tools/repo_pull/repo_patch.py b/tools/repo_pull/repo_patch.py index 55ce348b1..f2f74ac9a 100755 --- a/tools/repo_pull/repo_patch.py +++ b/tools/repo_pull/repo_patch.py @@ -40,8 +40,10 @@ def _parse_args(): parser.add_argument('--gitcookies', default=os.path.expanduser('~/.gitcookies'), help='Gerrit cookie file') - parser.add_argument('--limits', default=1000, + parser.add_argument('--limits', default=1000, type=int, help='Max number of change lists') + parser.add_argument('--start', default=0, type=int, + help='Skip first N changes in query') return parser.parse_args() @@ -63,7 +65,7 @@ def main(): # Query change lists url_opener = create_url_opener_from_args(args) change_lists = query_change_lists( - url_opener, args.gerrit, args.query, args.limits) + url_opener, args.gerrit, args.query, args.start, args.limits) # Download patch files num_changes = len(change_lists) diff --git a/tools/repo_pull/repo_pull.py b/tools/repo_pull/repo_pull.py index 6c8c28293..2d833ebc4 100755 --- a/tools/repo_pull/repo_pull.py +++ b/tools/repo_pull/repo_pull.py @@ -374,8 +374,10 @@ def _parse_args(): default=os.path.expanduser('~/.gitcookies'), help='Gerrit cookie file') parser.add_argument('--manifest', help='Manifest') - parser.add_argument('--limits', default=1000, + parser.add_argument('--limits', default=1000, type=int, help='Max number of change lists') + parser.add_argument('--start', default=0, type=int, + help='Skip first N changes in query') parser.add_argument('-m', '--merge', choices=sorted(_MERGE_COMMANDS.keys()), @@ -399,7 +401,8 @@ def _parse_args(): def _get_change_lists_from_args(args): """Query the change lists by args.""" url_opener = create_url_opener_from_args(args) - return query_change_lists(url_opener, args.gerrit, args.query, args.limits) + return query_change_lists(url_opener, args.gerrit, args.query, args.start, + args.limits) def _get_local_branch_name_from_args(args): diff --git a/tools/repo_pull/repo_review.py b/tools/repo_pull/repo_review.py index d33f790aa..fa99633be 100755 --- a/tools/repo_pull/repo_review.py +++ b/tools/repo_pull/repo_review.py @@ -93,8 +93,10 @@ def _parse_args(): parser.add_argument('--gitcookies', default=os.path.expanduser('~/.gitcookies'), help='Gerrit cookie file') - parser.add_argument('--limits', default=1000, + parser.add_argument('--limits', default=1000, type=int, help='Max number of change lists') + parser.add_argument('--start', default=0, type=int, + help='Skip first N changes in query') parser.add_argument('-l', '--label', nargs=2, action='append', help='Labels to be added') @@ -219,7 +221,7 @@ def main(): # Retrieve change lists change_lists = query_change_lists( - url_opener, args.gerrit, args.query, args.limits) + url_opener, args.gerrit, args.query, args.start, args.limits) if not change_lists: print('error: No matching change lists.', file=sys.stderr) sys.exit(1)