mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
712 lines
23 KiB
Python
712 lines
23 KiB
Python
7 years ago
|
#!/usr/bin/env python
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import subprocess
|
||
|
import datetime
|
||
|
import argparse
|
||
|
import commands
|
||
|
import re
|
||
|
|
||
|
|
||
|
git_repo_path = os.path.abspath(subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip())
|
||
|
|
||
|
|
||
|
|
||
|
# class include:
|
||
|
# def __init__(self, isInclude, isQuote, body, comment):
|
||
|
# self.isInclude = isInclude
|
||
|
# self.isQuote = isQuote
|
||
|
# self.body = body
|
||
|
# self.comment = comment
|
||
|
#
|
||
|
# def format(self):
|
||
|
# result = '%s %s%s%s' % (
|
||
|
# ('#include' if self.isInclude else '#import'),
|
||
|
# ('"' if self.isQuote else '<'),
|
||
|
# self.body.strip(),
|
||
|
# ('"' if self.isQuote else '>'),
|
||
|
# )
|
||
|
# if self.comment.strip():
|
||
|
# result += ' ' + self.comment.strip()
|
||
|
# return result
|
||
|
#
|
||
|
#
|
||
|
# def is_include_or_import(line):
|
||
|
# line = line.strip()
|
||
|
# if line.startswith('#include '):
|
||
|
# return True
|
||
|
# elif line.startswith('#import '):
|
||
|
# return True
|
||
|
# else:
|
||
|
# return False
|
||
|
#
|
||
|
#
|
||
|
# def parse_include(line):
|
||
|
# remainder = line.strip()
|
||
|
#
|
||
|
# if remainder.startswith('#include '):
|
||
|
# isInclude = True
|
||
|
# remainder = remainder[len('#include '):]
|
||
|
# elif remainder.startswith('#import '):
|
||
|
# isInclude = False
|
||
|
# remainder = remainder[len('#import '):]
|
||
|
# elif remainder == '//':
|
||
|
# return None
|
||
|
# elif not remainder:
|
||
|
# return None
|
||
|
# else:
|
||
|
# print ('Unexpected import or include: '+ line)
|
||
|
# sys.exit(1)
|
||
|
#
|
||
|
# comment = None
|
||
|
# if remainder.startswith('"'):
|
||
|
# isQuote = True
|
||
|
# endIndex = remainder.find('"', 1)
|
||
|
# if endIndex < 0:
|
||
|
# print ('Unexpected import or include: '+ line)
|
||
|
# sys.exit(1)
|
||
|
# body = remainder[1:endIndex]
|
||
|
# comment = remainder[endIndex+1:]
|
||
|
# elif remainder.startswith('<'):
|
||
|
# isQuote = False
|
||
|
# endIndex = remainder.find('>', 1)
|
||
|
# if endIndex < 0:
|
||
|
# print ('Unexpected import or include: '+ line)
|
||
|
# sys.exit(1)
|
||
|
# body = remainder[1:endIndex]
|
||
|
# comment = remainder[endIndex+1:]
|
||
|
# else:
|
||
|
# print ('Unexpected import or include: '+ remainder)
|
||
|
# sys.exit(1)
|
||
|
#
|
||
|
# return include(isInclude, isQuote, body, comment)
|
||
|
#
|
||
|
#
|
||
|
# def parse_includes(text):
|
||
|
# lines = text.split('\n')
|
||
|
#
|
||
|
# includes = []
|
||
|
# for line in lines:
|
||
|
# include = parse_include(line)
|
||
|
# if include:
|
||
|
# includes.append(include)
|
||
|
#
|
||
|
# return includes
|
||
|
#
|
||
|
#
|
||
|
# def sort_include_block(text, filepath, filename, file_extension):
|
||
|
# lines = text.split('\n')
|
||
|
#
|
||
|
# includes = parse_includes(text)
|
||
|
#
|
||
|
# blocks = []
|
||
|
#
|
||
|
# file_extension = file_extension.lower()
|
||
|
#
|
||
|
# for include in includes:
|
||
|
# include.isInclude = False
|
||
|
#
|
||
|
# if file_extension in ('c', 'cpp', 'hpp'):
|
||
|
# for include in includes:
|
||
|
# include.isInclude = True
|
||
|
# elif file_extension in ('m'):
|
||
|
# for include in includes:
|
||
|
# include.isInclude = False
|
||
|
#
|
||
|
# # Make sure matching header is first.
|
||
|
# matching_header_includes = []
|
||
|
# other_includes = []
|
||
|
# def is_matching_header(include):
|
||
|
# filename_wo_ext = os.path.splitext(filename)[0]
|
||
|
# include_filename_wo_ext = os.path.splitext(os.path.basename(include.body))[0]
|
||
|
# return filename_wo_ext == include_filename_wo_ext
|
||
|
# for include in includes:
|
||
|
# if is_matching_header(include):
|
||
|
# matching_header_includes.append(include)
|
||
|
# else:
|
||
|
# other_includes.append(include)
|
||
|
# includes = other_includes
|
||
|
#
|
||
|
# def formatBlock(includes):
|
||
|
# lines = [include.format() for include in includes]
|
||
|
# lines = list(set(lines))
|
||
|
# def include_sorter(a, b):
|
||
|
# # return cmp(a.lower(), b.lower())
|
||
|
# return cmp(a, b)
|
||
|
# # print 'before'
|
||
|
# # for line in lines:
|
||
|
# # print '\t', line
|
||
|
# # print
|
||
|
# lines.sort(include_sorter)
|
||
|
# # print 'after'
|
||
|
# # for line in lines:
|
||
|
# # print '\t', line
|
||
|
# # print
|
||
|
# # print
|
||
|
# # print 'filepath'
|
||
|
# # for line in lines:
|
||
|
# # print '\t', line
|
||
|
# # print
|
||
|
# return '\n'.join(lines)
|
||
|
#
|
||
|
# includeAngles = [include for include in includes if include.isInclude and not include.isQuote]
|
||
|
# includeQuotes = [include for include in includes if include.isInclude and include.isQuote]
|
||
|
# importAngles = [include for include in includes if (not include.isInclude) and not include.isQuote]
|
||
|
# importQuotes = [include for include in includes if (not include.isInclude) and include.isQuote]
|
||
|
# if matching_header_includes:
|
||
|
# blocks.append(formatBlock(matching_header_includes))
|
||
|
# if includeQuotes:
|
||
|
# blocks.append(formatBlock(includeQuotes))
|
||
|
# if includeAngles:
|
||
|
# blocks.append(formatBlock(includeAngles))
|
||
|
# if importQuotes:
|
||
|
# blocks.append(formatBlock(importQuotes))
|
||
|
# if importAngles:
|
||
|
# blocks.append(formatBlock(importAngles))
|
||
|
#
|
||
|
# return '\n'.join(blocks) + '\n'
|
||
|
#
|
||
|
#
|
||
|
# def sort_class_statement_block(text, filepath, filename, file_extension):
|
||
|
# lines = text.split('\n')
|
||
|
# lines = [line.strip() for line in lines if line.strip()]
|
||
|
# lines = list(set(lines))
|
||
|
# lines.sort()
|
||
|
# return '\n' + '\n'.join(lines) + '\n'
|
||
|
#
|
||
|
#
|
||
|
# def find_matching_section(text, match_test):
|
||
|
# lines = text.split('\n')
|
||
|
# first_matching_line_index = None
|
||
|
# for index, line in enumerate(lines):
|
||
|
# if match_test(line):
|
||
|
# first_matching_line_index = index
|
||
|
# break
|
||
|
#
|
||
|
# if first_matching_line_index is None:
|
||
|
# return None
|
||
|
#
|
||
|
# # Absorb any leading empty lines.
|
||
|
# while first_matching_line_index > 0:
|
||
|
# prev_line = lines[first_matching_line_index - 1]
|
||
|
# if prev_line.strip():
|
||
|
# break
|
||
|
# first_matching_line_index = first_matching_line_index - 1
|
||
|
#
|
||
|
# first_non_matching_line_index = None
|
||
|
# for index, line in enumerate(lines[first_matching_line_index:]):
|
||
|
# if not line.strip():
|
||
|
# # Absorb any trailing empty lines.
|
||
|
# continue
|
||
|
# if not match_test(line):
|
||
|
# first_non_matching_line_index = index + first_matching_line_index
|
||
|
# break
|
||
|
#
|
||
|
# text0 = '\n'.join(lines[:first_matching_line_index])
|
||
|
# if first_non_matching_line_index is None:
|
||
|
# text1 = '\n'.join(lines[first_matching_line_index:])
|
||
|
# text2 = None
|
||
|
# else:
|
||
|
# text1 = '\n'.join(lines[first_matching_line_index:first_non_matching_line_index])
|
||
|
# text2 = '\n'.join(lines[first_non_matching_line_index:])
|
||
|
#
|
||
|
# return text0, text1, text2
|
||
|
#
|
||
|
#
|
||
|
# def sort_matching_blocks(sort_name, filepath, filename, file_extension, text, match_func, sort_func):
|
||
|
# unprocessed = text
|
||
|
# processed = None
|
||
|
# while True:
|
||
|
# section = find_matching_section(unprocessed, match_func)
|
||
|
# # print '\t', 'sort_matching_blocks', section
|
||
|
# if not section:
|
||
|
# if processed:
|
||
|
# processed = '\n'.join((processed, unprocessed,))
|
||
|
# else:
|
||
|
# processed = unprocessed
|
||
|
# break
|
||
|
#
|
||
|
# text0, text1, text2 = section
|
||
|
#
|
||
|
# if processed:
|
||
|
# processed = '\n'.join((processed, text0,))
|
||
|
# else:
|
||
|
# processed = text0
|
||
|
#
|
||
|
# # print 'before:'
|
||
|
# # temp_lines = text1.split('\n')
|
||
|
# # for index, line in enumerate(temp_lines):
|
||
|
# # if index < 3 or index + 3 >= len(temp_lines):
|
||
|
# # print '\t', index, line
|
||
|
# # # print text1
|
||
|
# # print
|
||
|
# text1 = sort_func(text1, filepath, filename, file_extension)
|
||
|
# # print 'after:'
|
||
|
# # # print text1
|
||
|
# # temp_lines = text1.split('\n')
|
||
|
# # for index, line in enumerate(temp_lines):
|
||
|
# # if index < 3 or index + 3 >= len(temp_lines):
|
||
|
# # print '\t', index, line
|
||
|
# # print
|
||
|
# processed = '\n'.join((processed, text1,))
|
||
|
# if text2:
|
||
|
# unprocessed = text2
|
||
|
# else:
|
||
|
# break
|
||
|
#
|
||
|
# if text != processed:
|
||
|
# print sort_name, filepath
|
||
|
# return processed
|
||
|
#
|
||
|
#
|
||
|
# def find_class_statement_section(text):
|
||
|
# def is_class_statement(line):
|
||
|
# return line.strip().startswith('@class ')
|
||
|
#
|
||
|
# return find_matching_section(text, is_class_statement)
|
||
|
#
|
||
|
#
|
||
|
# def find_include_section(text):
|
||
|
# def is_include_line(line):
|
||
|
# return is_include_or_import(line)
|
||
|
# # return is_include_or_import_or_empty(line)
|
||
|
#
|
||
|
# return find_matching_section(text, is_include_line)
|
||
|
#
|
||
|
#
|
||
|
# def sort_includes(filepath, filename, file_extension, text):
|
||
|
# # print 'sort_includes', filepath
|
||
|
# if file_extension not in ('.h', '.m', '.mm'):
|
||
|
# return text
|
||
|
# return sort_matching_blocks('sort_includes', filepath, filename, file_extension, text, find_include_section, sort_include_block)
|
||
|
#
|
||
|
#
|
||
|
# def sort_class_statements(filepath, filename, file_extension, text):
|
||
|
# # print 'sort_class_statements', filepath
|
||
|
# if file_extension not in ('.h', '.m', '.mm'):
|
||
|
# return text
|
||
|
# return sort_matching_blocks('sort_class_statements', filepath, filename, file_extension, text, find_class_statement_section, sort_class_statement_block)
|
||
|
#
|
||
|
#
|
||
|
# def splitall(path):
|
||
|
# allparts = []
|
||
|
# while 1:
|
||
|
# parts = os.path.split(path)
|
||
|
# if parts[0] == path: # sentinel for absolute paths
|
||
|
# allparts.insert(0, parts[0])
|
||
|
# break
|
||
|
# elif parts[1] == path: # sentinel for relative paths
|
||
|
# allparts.insert(0, parts[1])
|
||
|
# break
|
||
|
# else:
|
||
|
# path = parts[0]
|
||
|
# allparts.insert(0, parts[1])
|
||
|
# return allparts
|
||
|
#
|
||
|
#
|
||
|
# def process(filepath):
|
||
|
#
|
||
|
# short_filepath = filepath[len(git_repo_path):]
|
||
|
# if short_filepath.startswith(os.sep):
|
||
|
# short_filepath = short_filepath[len(os.sep):]
|
||
|
#
|
||
|
# filename = os.path.basename(filepath)
|
||
|
# if filename.startswith('.'):
|
||
|
# return
|
||
|
# file_ext = os.path.splitext(filename)[1]
|
||
|
# if file_ext in ('.swift'):
|
||
|
# env_copy = os.environ.copy()
|
||
|
# env_copy["SCRIPT_INPUT_FILE_COUNT"] = "1"
|
||
|
# env_copy["SCRIPT_INPUT_FILE_0"] = '%s' % ( short_filepath, )
|
||
|
# lint_output = subprocess.check_output(['swiftlint', 'autocorrect', '--use-script-input-files'], env=env_copy)
|
||
|
# print lint_output
|
||
|
# try:
|
||
|
# lint_output = subprocess.check_output(['swiftlint', 'lint', '--use-script-input-files'], env=env_copy)
|
||
|
# except subprocess.CalledProcessError, e:
|
||
|
# lint_output = e.output
|
||
|
# print lint_output
|
||
|
#
|
||
|
# with open(filepath, 'rt') as f:
|
||
|
# text = f.read()
|
||
|
#
|
||
|
# original_text = text
|
||
|
#
|
||
|
# text = sort_includes(filepath, filename, file_ext, text)
|
||
|
# text = sort_class_statements(filepath, filename, file_ext, text)
|
||
|
#
|
||
|
# lines = text.split('\n')
|
||
|
# while lines and lines[0].startswith('//'):
|
||
|
# lines = lines[1:]
|
||
|
# text = '\n'.join(lines)
|
||
|
# text = text.strip()
|
||
|
#
|
||
|
# header = '''//
|
||
|
# // Copyright (c) %s Open Whisper Systems. All rights reserved.
|
||
|
# //
|
||
|
#
|
||
|
# ''' % (
|
||
|
# datetime.datetime.now().year,
|
||
|
# )
|
||
|
# text = header + text + '\n'
|
||
|
#
|
||
|
# if original_text == text:
|
||
|
# return
|
||
|
#
|
||
|
# print 'Updating:', short_filepath
|
||
|
#
|
||
|
# with open(filepath, 'wt') as f:
|
||
|
# f.write(text)
|
||
|
#
|
||
|
#
|
||
|
# def should_ignore_path(path):
|
||
|
# ignore_paths = [
|
||
|
# os.path.join(git_repo_path, '.git')
|
||
|
# ]
|
||
|
# for ignore_path in ignore_paths:
|
||
|
# if path.startswith(ignore_path):
|
||
|
# return True
|
||
|
# for component in splitall(path):
|
||
|
# if component.startswith('.'):
|
||
|
# return True
|
||
|
# if component.endswith('.framework'):
|
||
|
# return True
|
||
|
# if component in ('Pods', 'ThirdParty', 'Carthage',):
|
||
|
# return True
|
||
|
#
|
||
|
# return False
|
||
|
#
|
||
|
#
|
||
|
# def process_if_appropriate(filepath):
|
||
|
# filename = os.path.basename(filepath)
|
||
|
# if filename.startswith('.'):
|
||
|
# return
|
||
|
# file_ext = os.path.splitext(filename)[1]
|
||
|
# if file_ext not in ('.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift'):
|
||
|
# return
|
||
|
# if should_ignore_path(filepath):
|
||
|
# return
|
||
|
# process(filepath)
|
||
|
|
||
|
# class LineParser:
|
||
|
# def __init__(self, lines):
|
||
|
# self.lines = lines
|
||
|
#
|
||
|
# def
|
||
|
|
||
|
# def process_proto_file(proto_file_path, dst_dir_path, is_verbose):
|
||
|
|
||
|
|
||
|
|
||
|
class FileContext:
|
||
|
def __init__(self):
|
||
|
|
||
|
|
||
|
self.messages = []
|
||
|
self.enums = []
|
||
|
|
||
|
self.package = None
|
||
|
|
||
|
|
||
|
class MessageContext:
|
||
|
def __init__(self):
|
||
|
self.name = None
|
||
|
|
||
|
self.messages = []
|
||
|
self.enums = []
|
||
|
|
||
|
self.fields = []
|
||
|
self.field_names = set()
|
||
|
self.field_indices = set()
|
||
|
|
||
|
|
||
|
class EnumContext:
|
||
|
def __init__(self):
|
||
|
self.name = None
|
||
|
|
||
|
self.item_names = set()
|
||
|
self.item_indices = set()
|
||
|
self.item_map = {}
|
||
|
|
||
|
|
||
|
def line_parser(text, is_verbose):
|
||
|
# lineParser = LineParser(text.split('\n'))
|
||
|
|
||
|
for line in text.split('\n'):
|
||
|
line = line.strip()
|
||
|
# if not line:
|
||
|
# continue
|
||
|
|
||
|
comment_index = line.find('//')
|
||
|
if comment_index >= 0:
|
||
|
line = line[:comment_index].strip()
|
||
|
if not line:
|
||
|
continue
|
||
|
|
||
|
if is_verbose:
|
||
|
print 'line:', line
|
||
|
|
||
|
yield line
|
||
|
|
||
|
|
||
|
def parse_enum(proto_file_path, parser, parent_context, enum_name, is_verbose):
|
||
|
|
||
|
if is_verbose:
|
||
|
print '# enum:', enum_name
|
||
|
|
||
|
context = EnumContext()
|
||
|
context.name = enum_name
|
||
|
|
||
|
while True:
|
||
|
try:
|
||
|
line = parser.next()
|
||
|
except StopIteration:
|
||
|
raise Exception('Incomplete enum: %s' % proto_file_path)
|
||
|
|
||
|
if line == '}':
|
||
|
if is_verbose:
|
||
|
print
|
||
|
parent_context.enums.append(context)
|
||
|
return
|
||
|
|
||
|
item_regex = re.compile(r'^(.+?)\s*=\s*(\d+?)\s*;$')
|
||
|
item_match = item_regex.search(line)
|
||
|
if item_match:
|
||
|
item_name = item_match.group(1).strip()
|
||
|
item_index = item_match.group(2).strip()
|
||
|
|
||
|
if is_verbose:
|
||
|
print '\t enum item[%s]: %s' % (item_index, item_name)
|
||
|
|
||
|
if item_name in context.item_names:
|
||
|
raise Exception('Duplicate enum name[%s]: %s' % (proto_file_path, item_name))
|
||
|
context.item_names.add(item_name)
|
||
|
|
||
|
if item_index in context.item_indices:
|
||
|
raise Exception('Duplicate enum index[%s]: %s' % (proto_file_path, item_name))
|
||
|
context.item_indices.add(item_index)
|
||
|
|
||
|
context.item_map[item_index] = item_name
|
||
|
|
||
|
continue
|
||
|
|
||
|
raise Exception('Invalid enum syntax[%s]: %s' % (proto_file_path, line))
|
||
|
|
||
|
|
||
|
def optional_match_group(match, index):
|
||
|
group = match.group(index)
|
||
|
if group is None:
|
||
|
return None
|
||
|
return group.strip()
|
||
|
|
||
|
|
||
|
def parse_message(proto_file_path, parser, parent_context, message_name, is_verbose):
|
||
|
|
||
|
if is_verbose:
|
||
|
print '# message:', message_name
|
||
|
|
||
|
context = MessageContext()
|
||
|
context.name = message_name
|
||
|
|
||
|
while True:
|
||
|
try:
|
||
|
line = parser.next()
|
||
|
except StopIteration:
|
||
|
raise Exception('Incomplete message: %s' % proto_file_path)
|
||
|
|
||
|
if line == '}':
|
||
|
if is_verbose:
|
||
|
print
|
||
|
parent_context.messages.append(context)
|
||
|
return
|
||
|
|
||
|
enum_regex = re.compile(r'^enum\s+(.+?)\s+\{$')
|
||
|
enum_match = enum_regex.search(line)
|
||
|
if enum_match:
|
||
|
enum_name = enum_match.group(1).strip()
|
||
|
parse_enum(proto_file_path, parser, context, enum_name, is_verbose)
|
||
|
continue
|
||
|
|
||
|
message_regex = re.compile(r'^message\s+(.+?)\s+\{$')
|
||
|
message_match = message_regex.search(line)
|
||
|
if message_match:
|
||
|
message_name = message_match.group(1).strip()
|
||
|
parse_message(proto_file_path, parser, context, message_name, is_verbose)
|
||
|
continue
|
||
|
|
||
|
# Examples:
|
||
|
#
|
||
|
# optional bytes id = 1;
|
||
|
# optional bool isComplete = 2 [default = false];
|
||
|
item_regex = re.compile(r'^(optional|required|repeated)?\s*([\w\d]+?)\s+([\w\d]+?)\s*=\s*(\d+?)\s*(\[default = (true|false)\])?;$')
|
||
|
item_match = item_regex.search(line)
|
||
|
if item_match:
|
||
|
# print 'item_rules:', item_match.groups()
|
||
|
item_rules = optional_match_group(item_match, 1)
|
||
|
item_type = optional_match_group(item_match, 2)
|
||
|
item_name = optional_match_group(item_match, 3)
|
||
|
item_index = optional_match_group(item_match, 4)
|
||
|
# item_defaults_1 = optional_match_group(item_match, 5)
|
||
|
item_default = optional_match_group(item_match, 6)
|
||
|
|
||
|
# print 'item_rules:', item_rules
|
||
|
# print 'item_type:', item_type
|
||
|
# print 'item_name:', item_name
|
||
|
# print 'item_index:', item_index
|
||
|
# print 'item_default:', item_default
|
||
|
|
||
|
message_field = {
|
||
|
'rules': item_rules,
|
||
|
'type': item_type,
|
||
|
'name': item_name,
|
||
|
'index': item_index,
|
||
|
'default': item_default,
|
||
|
}
|
||
|
# print 'message_field:', message_field
|
||
|
|
||
|
if is_verbose:
|
||
|
print '\t message field[%s]: %s' % (item_index, str(message_field))
|
||
|
|
||
|
if item_name in context.field_names:
|
||
|
raise Exception('Duplicate message field name[%s]: %s' % (proto_file_path, item_name))
|
||
|
context.field_names.add(item_name)
|
||
|
|
||
|
if item_index in context.field_indices:
|
||
|
raise Exception('Duplicate message field index[%s]: %s' % (proto_file_path, item_name))
|
||
|
context.field_indices.add(item_index)
|
||
|
|
||
|
context.fields.append(message_field)
|
||
|
|
||
|
# if item_name in context.item_names:
|
||
|
# raise Exception('Duplicate message field[%s]: %s' % (proto_file_path, item_name))
|
||
|
# context.item_names.add(item_name)
|
||
|
#
|
||
|
# if item_index in context.item_map:
|
||
|
# raise Exception('Duplicate message field[%s]: %s' % (proto_file_path, item_index))
|
||
|
# context.item_map[item_index] = item_name
|
||
|
|
||
|
continue
|
||
|
|
||
|
raise Exception('Invalid message syntax[%s]: %s' % (proto_file_path, line))
|
||
|
|
||
|
|
||
|
def process_proto_file(proto_file_path, dst_dir_path, is_verbose):
|
||
|
with open(proto_file_path, 'rt') as f:
|
||
|
text = f.read()
|
||
|
|
||
|
multiline_comment_regex = re.compile(r'/\*.*?\*/', re.MULTILINE|re.DOTALL)
|
||
|
text = multiline_comment_regex.sub('', text)
|
||
|
|
||
|
syntax_regex = re.compile(r'^syntax ')
|
||
|
package_regex = re.compile(r'^package\s+(.+);')
|
||
|
option_regex = re.compile(r'^option ')
|
||
|
|
||
|
parser = line_parser(text, is_verbose)
|
||
|
|
||
|
# lineParser = LineParser(text.split('\n'))
|
||
|
|
||
|
context = FileContext()
|
||
|
|
||
|
while True:
|
||
|
try:
|
||
|
line = parser.next()
|
||
|
except StopIteration:
|
||
|
break
|
||
|
# if not line:
|
||
|
# break
|
||
|
# for line in text.split('\n'):
|
||
|
# line = line.strip()
|
||
|
# if not line:
|
||
|
# continue
|
||
|
|
||
|
# if is_verbose:
|
||
|
# print 'line:', line
|
||
|
|
||
|
if syntax_regex.search(line):
|
||
|
if is_verbose:
|
||
|
print '# Ignoring syntax'
|
||
|
continue
|
||
|
|
||
|
if option_regex.search(line):
|
||
|
if is_verbose:
|
||
|
print '# Ignoring option'
|
||
|
continue
|
||
|
|
||
|
package_match = package_regex.search(line)
|
||
|
if package_match:
|
||
|
if context.package:
|
||
|
raise Exception('More than one package statement: %s' % proto_file_path)
|
||
|
context.package = package_match.group(1).strip()
|
||
|
|
||
|
if is_verbose:
|
||
|
print '# package:', context.package
|
||
|
continue
|
||
|
|
||
|
message_regex = re.compile(r'^message\s+(.+?)\s+\{$')
|
||
|
message_match = message_regex.search(line)
|
||
|
if message_match:
|
||
|
message_name = message_match.group(1).strip()
|
||
|
parse_message(proto_file_path, parser, context, message_name, is_verbose)
|
||
|
continue
|
||
|
|
||
|
raise Exception('Invalid syntax[%s]: %s' % (proto_file_path, line))
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
|
||
|
parser = argparse.ArgumentParser(description='Protocol Buffer Swift Wrapper Generator.')
|
||
|
# parser.add_argument('--all', action='store_true', help='process all files in or below current dir')
|
||
|
# parser.add_argument('--path', help='used to specify a path to a file.')
|
||
|
parser.add_argument('--proto-dir', help='dir path of the proto schema file.')
|
||
|
parser.add_argument('--proto-file', help='filename of the proto schema file.')
|
||
|
parser.add_argument('--wrapper-prefix', help='name prefix for generated wrappers.')
|
||
|
parser.add_argument('--proto-prefix', help='name prefix for proto bufs.')
|
||
|
parser.add_argument('--dst-dir', help='path to the destination directory.')
|
||
|
parser.add_argument('--verbose', action='store_true', help='enables verbose logging')
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
proto_file_path = os.path.abspath(os.path.join(args.proto_dir, args.proto_file))
|
||
|
if not os.path.exists(proto_file_path):
|
||
|
raise Exception('File does not exist: %s' % proto_file_path)
|
||
|
|
||
|
dst_dir_path = os.path.abspath(args.dst_dir)
|
||
|
if not os.path.exists(dst_dir_path):
|
||
|
raise Exception('Destination does not exist: %s' % dst_dir_path)
|
||
|
|
||
|
is_verbose = args.verbose
|
||
|
|
||
|
process_proto_file(proto_file_path, dst_dir_path, is_verbose)
|
||
|
print 'complete.'
|
||
|
|
||
|
# if args.all:
|
||
|
# for rootdir, dirnames, filenames in os.walk(git_repo_path):
|
||
|
# for filename in filenames:
|
||
|
# file_path = os.path.abspath(os.path.join(rootdir, filename))
|
||
|
# process_if_appropriate(file_path)
|
||
|
# elif args.path:
|
||
|
# for rootdir, dirnames, filenames in os.walk(args.path):
|
||
|
# for filename in filenames:
|
||
|
# file_path = os.path.abspath(os.path.join(rootdir, filename))
|
||
|
# process_if_appropriate(file_path)
|
||
|
# else:
|
||
|
# filepaths = []
|
||
|
#
|
||
|
# # Staging
|
||
|
# output = commands.getoutput('git diff --cached --name-only --diff-filter=ACMR')
|
||
|
# filepaths.extend([line.strip() for line in output.split('\n')])
|
||
|
#
|
||
|
# # Working
|
||
|
# output = commands.getoutput('git diff --name-only --diff-filter=ACMR')
|
||
|
# filepaths.extend([line.strip() for line in output.split('\n')])
|
||
|
#
|
||
|
# # Only process each path once.
|
||
|
# filepaths = sorted(set(filepaths))
|
||
|
#
|
||
|
# for filepath in filepaths:
|
||
|
# filepath = os.path.abspath(os.path.join(git_repo_path, filepath))
|
||
|
# process_if_appropriate(filepath)
|
||
|
|
||
|
# print 'git clang-format...'
|
||
|
# print commands.getoutput('git clang-format')
|