From 156cfec096fd71cbd6d15592e80d164b8f3b55ad Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 19 Dec 2012 00:12:26 +0100 Subject: [PATCH 01/37] Cleanup Clar to make it SIMPLER --- .gitignore | 7 +- .gitmodules | 3 + CMakeLists.txt | 21 +- tests-clar/clar | 347 +----------------- tests-clar/clar_helpers.c | 11 - tests-clar/clar_libgit2.h | 2 +- tests-clar/main.c | 16 + .../{clone/network.c => online/clone.c} | 2 - tests-clar/{network => online}/fetch.c | 2 - .../network.c => online/fetchhead.c} | 4 +- tests-clar/{network => online}/push.c | 6 +- tests-clar/{network => online}/push_util.c | 0 tests-clar/{network => online}/push_util.h | 0 13 files changed, 38 insertions(+), 383 deletions(-) create mode 100644 .gitmodules mode change 100755 => 160000 tests-clar/clar create mode 100644 tests-clar/main.c rename tests-clar/{clone/network.c => online/clone.c} (99%) rename tests-clar/{network => online}/fetch.c (99%) rename tests-clar/{fetchhead/network.c => online/fetchhead.c} (97%) rename tests-clar/{network => online}/push.c (99%) rename tests-clar/{network => online}/push_util.c (100%) rename tests-clar/{network => online}/push_util.h (100%) diff --git a/.gitignore b/.gitignore index 5441aa597..b81a1b13c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ -/tests-clar/clar.h -/tests-clar/clar_main.c -/tests-clar/clar_main.c.rule +/tests-clar/clar.suite +/tests-clar/.clarcache /apidocs /trash-*.exe /libgit2.pc @@ -28,4 +27,4 @@ CMake* .DS_Store *~ tags -mkmf.log \ No newline at end of file +mkmf.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..5d7eda9ac --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tests-clar/clar"] + path = tests-clar/clar + url = https://github.com/vmg/clar.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 696d6a088..fe9f5afa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,6 @@ INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) # Tests IF (BUILD_CLAR) - FIND_PACKAGE(PythonInterp REQUIRED) SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar/resources/") @@ -243,23 +242,25 @@ IF (BUILD_CLAR) ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\") INCLUDE_DIRECTORIES(${CLAR_PATH}) - FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/clar_helpers.c ${CLAR_PATH}/testlib.c) + FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/clar_helpers.c) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_COMMAND( - OUTPUT ${CLAR_PATH}/clar_main.c ${CLAR_PATH}/clar.h - COMMAND ${PYTHON_EXECUTABLE} clar . - DEPENDS ${CLAR_PATH}/clar ${SRC_TEST} + OUTPUT ${CLAR_PATH}/clar.suite + COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . + DEPENDS ${CLAR_PATH}/clar.suite ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) - ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) + + ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${CLAR_PATH}/main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES}) TARGET_OS_LIBRARIES(libgit2_clar) MSVC_SPLIT_SOURCES(libgit2_clar) - IF (MSVC_IDE) - # Precompiled headers - SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h") - ENDIF () + IF (MSVC_IDE) + # Precompiled headers + SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h") + ENDIF () ENABLE_TESTING() ADD_TEST(libgit2_clar libgit2_clar -iall) diff --git a/tests-clar/clar b/tests-clar/clar deleted file mode 100755 index 7634b2c76..000000000 --- a/tests-clar/clar +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env python - -from __future__ import with_statement -from string import Template -import re, fnmatch, os, codecs - -VERSION = "0.10.0" - -TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{" - -EVENT_CB_REGEX = re.compile( - r"^(void\s+clar_on_(\w+)\(\s*void\s*\))\s*\{", - re.MULTILINE) - -SKIP_COMMENTS_REGEX = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE) - -CATEGORY_REGEX = re.compile(r"CL_IN_CATEGORY\(\s*\"([^\"]+)\"\s*\)") - -CLAR_HEADER = """ -/* - * Clar v%s - * - * This is an autogenerated file. Do not modify. - * To add new unit tests or suites, regenerate the whole - * file with `./clar` - */ -""" % VERSION - -CLAR_EVENTS = [ - 'init', - 'shutdown', - 'test', - 'suite' -] - -def main(): - from optparse import OptionParser - - parser = OptionParser() - - parser.add_option('-c', '--clar-path', dest='clar_path') - parser.add_option('-v', '--report-to', dest='print_mode', default='default') - - options, args = parser.parse_args() - - for folder in args or ['.']: - builder = ClarTestBuilder(folder, - clar_path = options.clar_path, - print_mode = options.print_mode) - - builder.render() - - -class ClarTestBuilder: - def __init__(self, path, clar_path = None, print_mode = 'default'): - self.declarations = [] - self.suite_names = [] - self.callback_data = {} - self.suite_data = {} - self.category_data = {} - self.event_callbacks = [] - - self.clar_path = os.path.abspath(clar_path) if clar_path else None - - self.path = os.path.abspath(path) - self.modules = [ - "clar_sandbox.c", - "clar_fixtures.c", - "clar_fs.c", - "clar_categorize.c", - ] - - self.modules.append("clar_print_%s.c" % print_mode) - - print("Loading test suites...") - - for root, dirs, files in os.walk(self.path): - module_root = root[len(self.path):] - module_root = [c for c in module_root.split(os.sep) if c] - - tests_in_module = fnmatch.filter(files, "*.c") - - for test_file in tests_in_module: - full_path = os.path.join(root, test_file) - test_name = "_".join(module_root + [test_file[:-2]]) - - with codecs.open(full_path, 'r', 'utf-8') as f: - self._process_test_file(test_name, f.read()) - - if not self.suite_data: - raise RuntimeError( - 'No tests found under "%s"' % path) - - def render(self): - main_file = os.path.join(self.path, 'clar_main.c') - with open(main_file, "w") as out: - out.write(self._render_main()) - - header_file = os.path.join(self.path, 'clar.h') - with open(header_file, "w") as out: - out.write(self._render_header()) - - print ('Written Clar suite to "%s"' % self.path) - - ##################################################### - # Internal methods - ##################################################### - - def _render_cb(self, cb): - return '{"%s", &%s}' % (cb['short_name'], cb['symbol']) - - def _render_suite(self, suite, index): - template = Template( -r""" - { - ${suite_index}, - "${clean_name}", - ${initialize}, - ${cleanup}, - ${categories}, - ${cb_ptr}, ${cb_count} - } -""") - - callbacks = {} - for cb in ['initialize', 'cleanup']: - callbacks[cb] = (self._render_cb(suite[cb]) - if suite[cb] else "{NULL, NULL}") - - if len(self.category_data[suite['name']]) > 0: - cats = "_clar_cat_%s" % suite['name'] - else: - cats = "NULL" - - return template.substitute( - suite_index = index, - clean_name = suite['name'].replace("_", "::"), - initialize = callbacks['initialize'], - cleanup = callbacks['cleanup'], - categories = cats, - cb_ptr = "_clar_cb_%s" % suite['name'], - cb_count = suite['cb_count'] - ).strip() - - def _render_callbacks(self, suite_name, callbacks): - template = Template( -r""" -static const struct clar_func _clar_cb_${suite_name}[] = { - ${callbacks} -}; -""") - callbacks = [ - self._render_cb(cb) - for cb in callbacks - if cb['short_name'] not in ('initialize', 'cleanup') - ] - - return template.substitute( - suite_name = suite_name, - callbacks = ",\n\t".join(callbacks) - ).strip() - - def _render_categories(self, suite_name, categories): - template = Template( -r""" -static const char *_clar_cat_${suite_name}[] = { "${categories}", NULL }; -""") - if len(categories) > 0: - return template.substitute( - suite_name = suite_name, - categories = '","'.join(categories) - ).strip() - else: - return "" - - def _render_event_overrides(self): - overrides = [] - for event in CLAR_EVENTS: - if event in self.event_callbacks: - continue - - overrides.append( - "#define clar_on_%s() /* nop */" % event - ) - - return '\n'.join(overrides) - - def _render_header(self): - template = Template(self._load_file('clar.h')) - - declarations = "\n".join( - "extern %s;" % decl - for decl in sorted(self.declarations) - ) - - return template.substitute( - extern_declarations = declarations, - ) - - def _render_main(self): - template = Template(self._load_file('clar.c')) - suite_names = sorted(self.suite_names) - - suite_data = [ - self._render_suite(self.suite_data[s], i) - for i, s in enumerate(suite_names) - ] - - callbacks = [ - self._render_callbacks(s, self.callback_data[s]) - for s in suite_names - ] - - callback_count = sum( - len(cbs) for cbs in self.callback_data.values() - ) - - categories = [ - self._render_categories(s, self.category_data[s]) - for s in suite_names - ] - - return template.substitute( - clar_modules = self._get_modules(), - clar_callbacks = "\n".join(callbacks), - clar_categories = "".join(categories), - clar_suites = ",\n\t".join(suite_data), - clar_suite_count = len(suite_data), - clar_callback_count = callback_count, - clar_event_overrides = self._render_event_overrides(), - ) - - def _load_file(self, filename): - if self.clar_path: - filename = os.path.join(self.clar_path, filename) - with open(filename) as cfile: - return cfile.read() - - else: - import zlib, base64, sys - content = CLAR_FILES[filename] - - if sys.version_info >= (3, 0): - content = bytearray(content, 'utf_8') - content = base64.b64decode(content) - content = zlib.decompress(content) - return str(content, 'utf-8') - else: - content = base64.b64decode(content) - return zlib.decompress(content) - - def _get_modules(self): - return "\n".join(self._load_file(f) for f in self.modules) - - def _skip_comments(self, text): - def _replacer(match): - s = match.group(0) - return "" if s.startswith('/') else s - - return re.sub(SKIP_COMMENTS_REGEX, _replacer, text) - - def _process_test_file(self, suite_name, contents): - contents = self._skip_comments(contents) - - self._process_events(contents) - self._process_declarations(suite_name, contents) - self._process_categories(suite_name, contents) - - def _process_events(self, contents): - for (decl, event) in EVENT_CB_REGEX.findall(contents): - if event not in CLAR_EVENTS: - continue - - self.declarations.append(decl) - self.event_callbacks.append(event) - - def _process_declarations(self, suite_name, contents): - callbacks = [] - initialize = cleanup = None - - regex_string = TEST_FUNC_REGEX % suite_name - regex = re.compile(regex_string, re.MULTILINE) - - for (declaration, symbol, short_name) in regex.findall(contents): - data = { - "short_name" : short_name, - "declaration" : declaration, - "symbol" : symbol - } - - if short_name == 'initialize': - initialize = data - elif short_name == 'cleanup': - cleanup = data - else: - callbacks.append(data) - - if not callbacks: - return - - tests_in_suite = len(callbacks) - - suite = { - "name" : suite_name, - "initialize" : initialize, - "cleanup" : cleanup, - "cb_count" : tests_in_suite - } - - if initialize: - self.declarations.append(initialize['declaration']) - - if cleanup: - self.declarations.append(cleanup['declaration']) - - self.declarations += [ - callback['declaration'] - for callback in callbacks - ] - - callbacks.sort(key=lambda x: x['short_name']) - self.callback_data[suite_name] = callbacks - self.suite_data[suite_name] = suite - self.suite_names.append(suite_name) - - print(" %s (%d tests)" % (suite_name, tests_in_suite)) - - def _process_categories(self, suite_name, contents): - self.category_data[suite_name] = [ - cat for cat in CATEGORY_REGEX.findall(contents) ] - - -CLAR_FILES = { -"clar.c" : r"""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""", -"clar_print_default.c" : r"""eJyFU8Fu2zAMPdtfwQUwIgVuenew9tZTsMuwU1sYqiW3AhzJkOhswNB/n0Q5rRws6Ukmxff4RD6XHgXqDo5WS+gG4drRaYOtNhpZ+ABUHtvOTgZriLGfNKpTorPGI3RvwsEmXRhxUJ6Xf8uCRUr+Cd+VBVH3bLW3QioJlUxsvoHKP5lVDbEjX3TIWTOGnygcKhlAIftelhde4d8mlPa3+folMaGcsy4lLr0gpTLkRy4D78pPoU8maSxIlVOjddhSrWdXpVMN6TbT4TRpj27qMJVRAWzoILmnlhAGy+FB6GFyqqG5Bgqeq6p801QeWOU5PIagks/weIPhiOVlURDrzR09NIvjLGK4Mhak8p3TI2q7gPR6yBGDNmF90+FFuTOeObvQBScjzHVpqAf/SlW6BzZfZM3h23f48Wu/54H+Ek9Wzpfbue4fa6JSlts8SQ9+TJ7JXpISfZi7kuf+iYDdMkOYzNJVF/QmNNzD+mENDay36y/00YbY///D3ObaSPWHVN1uwFg7wuZ2aWeqOLN4kn2tv3gJhl70D9uqYbvdUrOjaAcdroR7HXcU+vjnshjXkBZbHPt5Bh5lWBjla4LwhFFGsjl8L/8BsUiTTQ==""", -"clar_print_tap.c" : r"""eJyNVE1vnDAQPcOvmGWFBAiQot6yaqr2HFU9tLdKyAGzscLayDbbVlX+e8cDJPbuJtsTzPObmTcfdmwss6KFoxIdtAPTzaiFtI2Qwmb4A5Yb27RqkrYEZ5tJWL4CrZLGQvvINBTzgWQHbvL4bxxlLmT+6r5bIY94gq08ktBnyffP3+DItRFKws2HnzLJd/FzHL8h2TxOtlO/5HXZDuBaKz0D/yM3xDznXRxHoodsEwSMXmrYwsiM4R2wYYC0I2GZybGY0hOJhUV8MDxw7JkY0BGd2EHJ/am3l7BEvyiMtoa5qeu0O8/2dhspLPVQTod1xMbqqbUzjQhQ0MdrHbJdL9a8AFVVzSPzMJy5YXsOt5Ca1yKqu7mWg9mHdMNx/ML+uaVenEWj0QCcRSM8pLri4QLV4SGzx6ZfYjo8ZA5CrszOZzq8wXY8cJ2v67Ecddy0WozWbfTmI3z9cX/vLwuARzgV4B3lYafrur52OZSk1fEvLO2Du4bzhZhNUj0D8/rRhNdUqXFLWC3CUPiyop8gkcqCekqwGQl+3Jkf8MXEdHFE8kmc5qPSy86Z7EoFNNbs8pvj33IhO/470L2FoihQNWTbtMudQY313X3X92WwB5QcyMC9Ld0QKOeRNYPAI6b3445MjIQOzi5hWfF+UWbwxZrwRUq+YCMBfzdAO348JVAKFyKfY3LZZYv5HP8D5Mbj9w==""", -"clar_sandbox.c" : r"""eJydVWtP4kAU/dz+iism0gpKfWQ3G9YPm+gasioEMJgomdR2KhPplMwM7KLxv++dTqEP0DVrTKjcO+eec+6cKpWvWADBxBdAgqkvyMxXk/tT79uXcdu2pSkzrmwmycKfspCoeJY2OUHCpTJH9/UXrv1qW4PhjyEZglR42mIROBrC0eUm7Enlws4ZeK5tWYKqueDgrfp2BqQzOO/08cChVCROQupW+7Jnxw8CKmWGOiLdXy6cadi2/VbiHDFe5JsyfZxHERVNkOyFEgVTyp8M9V0W8ZBGQEadm5Nj28pwjMqse4EGBcmcKziD03alx+BTvkCjhLwfYw8aYtWG1z3UVWuCfko/Lszn7eCi3+t3f3auLmo2WG8oEaxsEtN6o0SAwxDHawOD7/n4NjQazE3hK7Ox+YkqfHDWRNgYjbGMyfilNlWfUozPqZ6SVjbXq1vNCJQpeDBbOivvsNRcOaehC0uyrDcbf22rtQ+dCNSE6m4mEh5TtC1MqOR19NNfgs+XasL4UxOUWIJKYC4ptHA+7Lfsd0jVdL2W8arSMsUSswIxJLVLp5Ia6EuqhjSe9TSocz7q9s9dc6wJBq5y+XYpD1lkdA0nTIJcSkXjtaApe6YooKRFiw/mQqTCmaCBSrD4gbjDd5UdfiRr9efBUTEAi4SFkEZ6zqXPw8fkj6O/S2OqCRTy7o11gOoPXj1XjVcDI1FMRDBBFcgSaRYMiSQRcQGsmkL0k01DklEwStc8CrdXF4jy2TRNTi3F09bcpT81nbZ1ZFcvjXLAcw4m3klUpOVigIpvHu2WbSEYTkO/8aEsoqr+FXD1PBExLu2FpnT1onvdQecOMKm/fRGCnPpyQmW65EKUrY0oaxF5iKv7YNk+HtJ9WFalBPVWfR219SIqGFrZARyN9RsX+82gcr3RyMH0PVpdu7wLGpppM1/ONmdxDDZllgF6xjgNHUKuOzeXo5NjQtyMXPyMkZmVjqLMm9urq4296P74Wd+34la9r5638S9EH8BkF0enKytPJfKf92ML7v8QWb1i8NQn5a5XmOe6HKEU4fMhhr29banbngCNYpJdJLrVixK9v7GvgW8=""", -"clar_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfZEwQSglZmrBAl5Qkk6n43236tWbKfMvNOfecc+81llhBgSppLNAN0XCOuNjbnWa4InYTjpE1MSzxuD1Vki2L0BcKTKfn0EYgu57d3uRpjYhPhi1opSwumUwRCvo3zMFYXT9C5xA5stWSVh9hI5FAa+wUFG//osgJCA5tmQ1SF3CVw9kcppfTCAWBj8ZxDg3UN4/zZ7MaHBrHSBw7vpcJ4mGS5Ijtai9qnannNqk1q7myXU+KvhGaCF4wDnfPiyV+eHpbvS7v8cti9YjGq6Yl7lzCkxfo1L0j/lJOwOtrUrwrUcDBBRsii7Xan3bjBlNVL2WUzuMkgGlJdLuIP21oyYjcVf/a6G3ozXTQPRqmsZkwWQiOfgAVGffP""", -"clar_fs.c" : r"""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""", -"clar_categorize.c" : r"""eJydVV1v0zAUfU5+xV3RKudj0/ZcOqkqAyGVIU3bA9omy01dsJQlJXYRY+K/c32ddE6WtMBLGzv365x77s2blVyrQsJ8Mbvm89nN5YfP11/4u8v3s9vFDYzwrdjmZhSG5mkj8QTaVNvMwHMYZGWhDWTfRAVxXIhHqSdhoAq8KreFqZ9FnpfZJPwNWS4qngkjv5bVE8+VRotQG2FU1vMOuH+nfkkuC7HM5erFiTK1HFVBvqwnXGx/U/BLRoMofHZVKqx2XVbAFEzhbAIK3oL1OLlwWCBJVBQGgVoDQwIyoWX2uGEYIq3tCP+deohgihGsbVBJs60KOMfY9eMZErGr/0epVh0AYrXipvwvEFhYPxm1D9rZolwhSCJ5eBDhYlojoY5FtsGBdwHJFM6x/uaS8CJZrKWCqJJkzSx+RgjjyHNI/RwQg8bOlutWjCjCJMiSn+fOKzRJHjAt4jnApdML65BF74ixYebHQ9ojGl2Ev0rOESazELkBvVVGckLQdLCeJPKk1xDTn6b6aj+rzBbFhLxbfg22d4gja94Vt1cOXiSJ1QbZYEi0cnWgnE8bFnC4LXoYj4lHOji3/lJImT5Ldsz4p9nHKz6fd9iiUSKMTjGiYcgdl8RHPUIn4M2fSJeHOrGpMHHTwJYaNhVuvp/+CgiD77qsDGuEO6SDU6dlxD5o4RqNFn0KT1/j723S/ui7pUQQ12x0rI/1fTFKwSFLh/13y6rboM4K0U6XHfqGdOvGyteqzsRu1xztR2OB/KOmKSplxtWwk+nLlhv4OljJ7hnxAzNkITUD4qedAKGFoylc3S4WE7AnNyDDu3lPGRQt6nxH2h+SPx6FmFM=""", -"clar.h" : r"""eJy9VV1vmzAUfS6/wg17gAi1TR+7tlIUJWukqJvaVNueLGNMsQaG2mbNNO2/7xpICF/Juoe+JOZe33uOOecam4ciYCHCeLaaPuD1/HGN7zC2bAhywTpxy+aCxnnA0LXSQcz9s+jWsn6mPEA0JhJjohST2rFOuNCIpiLgmqfCs05grSASEYnGIY+ZV26JAaWVZVKmshULmKKSZ1UvU6iiNI8DTPxUavdjDwfMXnISY+Xs9/GGH6BpJwCNh/pyxxT0FfV12bbBimlMY0ZEnjlFzBlXj275PHY9VC7SjLzkrKaAQ9UoNW1tHhr5CpEWy2/rp4c5/jJd31n7HEwp3+hcMqepQhHDgiQNlCqsiAj8dPOWki27AyU2A0uE1s5gsxVe3uPZdD3/9PnhuwML17LOx2MLjdG0eN8gOUoIlalCr1xHiG2ymFOuUeETlDClyDOD/ee7pkApyZXGGSiGHSiQHjIOcpsmLTIuur1BFx44fbFczTE2q9XyvliNFrmgBQFK4hiFBHwbXKERsuueHpq4HWCz8zjw9SDufJMxqlmAwgYBnRYcjjCobHoU/nT43IAv4b0aYK6QSDXSMmd9uFutZhGjP/5DJ2rq3kmoC7eL/M5K9VF4B6Eujg2VSP9xnCpKfRN2/7Ra9Y9Cq2j/nXeKqqPvKppuLrcPm+7YOWq71QhdC3ZI1V5plx08S7GlXdF7kkUqqTERdIPL8vyVSMHFc5t9QaDHJ0PuWDO4hsthOBv1XxYV0lu6fi1LUJBL86cNCNswmhtXXY16PLf+lcHhSMt57dO1Pttq4qnLJqVdDpKu50Da2zHcERw96oJXwlVCNI2KYVAT+IU5MsvLgQtz912feLwfmDuQBGDeC2zzGoQfBvEdf+L5QyCnp5B2PfPXD+TXQP5hoMzJJl52uTdJDkRcdHODHAjvSWRUTJiO0gD0M7SIkaoU6cNvttFMCryf+WNtP+Z/AaQwXp0=""" -} -if __name__ == '__main__': - main() diff --git a/tests-clar/clar b/tests-clar/clar new file mode 160000 index 000000000..161e8cd0f --- /dev/null +++ b/tests-clar/clar @@ -0,0 +1 @@ +Subproject commit 161e8cd0f7642385d22153052fbcf770517de6c1 diff --git a/tests-clar/clar_helpers.c b/tests-clar/clar_helpers.c index b718d4305..ce3ec4af4 100644 --- a/tests-clar/clar_helpers.c +++ b/tests-clar/clar_helpers.c @@ -2,17 +2,6 @@ #include "posix.h" #include "path.h" -void clar_on_init(void) -{ - git_threads_init(); -} - -void clar_on_shutdown(void) -{ - giterr_clear(); - git_threads_shutdown(); -} - void cl_git_mkfile(const char *filename, const char *content) { int fd; diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 91a542654..15b5daaf3 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -1,7 +1,7 @@ #ifndef __CLAR_LIBGIT2__ #define __CLAR_LIBGIT2__ -#include "clar.h" +#include "clar/clar.h" #include #include "common.h" diff --git a/tests-clar/main.c b/tests-clar/main.c new file mode 100644 index 000000000..e9b3b641c --- /dev/null +++ b/tests-clar/main.c @@ -0,0 +1,16 @@ +#include "clar_libgit2.h" + +int main(int argc, char *argv[]) +{ + int res; + + git_threads_init(); + + /* Run the test suite */ + res = clar_test(argc, argv); + + giterr_clear(); + git_threads_shutdown(); + + return res; +} diff --git a/tests-clar/clone/network.c b/tests-clar/online/clone.c similarity index 99% rename from tests-clar/clone/network.c rename to tests-clar/online/clone.c index d3009660e..f783a5a8b 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/online/clone.c @@ -3,8 +3,6 @@ #include "git2/clone.h" #include "repository.h" -CL_IN_CATEGORY("network") - #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" #define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository" diff --git a/tests-clar/network/fetch.c b/tests-clar/online/fetch.c similarity index 99% rename from tests-clar/network/fetch.c rename to tests-clar/online/fetch.c index 4cc23318d..979b02303 100644 --- a/tests-clar/network/fetch.c +++ b/tests-clar/online/fetch.c @@ -1,7 +1,5 @@ #include "clar_libgit2.h" -CL_IN_CATEGORY("network") - static git_repository *_repo; static int counter; diff --git a/tests-clar/fetchhead/network.c b/tests-clar/online/fetchhead.c similarity index 97% rename from tests-clar/fetchhead/network.c rename to tests-clar/online/fetchhead.c index dc223e2aa..a6b8a6ffd 100644 --- a/tests-clar/fetchhead/network.c +++ b/tests-clar/online/fetchhead.c @@ -2,11 +2,9 @@ #include "repository.h" #include "fetchhead.h" -#include "fetchhead_data.h" +#include "../fetchhead/fetchhead_data.h" #include "git2/clone.h" -CL_IN_CATEGORY("network") - #define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" static git_repository *g_repo; diff --git a/tests-clar/network/push.c b/tests-clar/online/push.c similarity index 99% rename from tests-clar/network/push.c rename to tests-clar/online/push.c index 788af5267..8878e6356 100644 --- a/tests-clar/network/push.c +++ b/tests-clar/online/push.c @@ -5,8 +5,6 @@ #include "../submodule/submodule_helpers.h" #include "push_util.h" -CL_IN_CATEGORY("network") - static git_repository *_repo; static char *_remote_url; @@ -112,7 +110,7 @@ static void do_verify_push_status(git_push *push, const push_status expected[], /** * Verifies that after git_push_finish(), refs on a remote have the expected * names, oids, and order. - * + * * @param remote remote to verify * @param expected_refs expected remote refs after push * @param expected_refs_len length of expected_refs @@ -224,7 +222,7 @@ void test_network_push__cleanup(void) /** * Calls push and relists refs on remote to verify success. - * + * * @param refspecs refspecs to push * @param refspecs_len length of refspecs * @param expected_refs expected remote refs after push diff --git a/tests-clar/network/push_util.c b/tests-clar/online/push_util.c similarity index 100% rename from tests-clar/network/push_util.c rename to tests-clar/online/push_util.c diff --git a/tests-clar/network/push_util.h b/tests-clar/online/push_util.h similarity index 100% rename from tests-clar/network/push_util.h rename to tests-clar/online/push_util.h From b0a45829750825bdc417b0c3e5947c762faebbe0 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 19 Dec 2012 01:10:13 +0100 Subject: [PATCH 02/37] Bump the Clar submodule --- CMakeLists.txt | 2 +- tests-clar/clar | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe9f5afa1..69768443f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,7 +263,7 @@ IF (BUILD_CLAR) ENDIF () ENABLE_TESTING() - ADD_TEST(libgit2_clar libgit2_clar -iall) + ADD_TEST(libgit2_clar libgit2_clar) ENDIF () IF (TAGS) diff --git a/tests-clar/clar b/tests-clar/clar index 161e8cd0f..1febaef17 160000 --- a/tests-clar/clar +++ b/tests-clar/clar @@ -1 +1 @@ -Subproject commit 161e8cd0f7642385d22153052fbcf770517de6c1 +Subproject commit 1febaef178ccc12d3bdc4568a23f089b520a987b From 5c2d3f6d5deeec84c7cadc7d9f61b00952f1d56f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 04:17:31 +0100 Subject: [PATCH 03/37] Add build dependency for clar. Also, fuck you CMake. Fuck you. --- CMakeLists.txt | 12 +++++++++--- tests-clar/clar | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69768443f..f2cf252d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,17 +242,23 @@ IF (BUILD_CLAR) ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\") INCLUDE_DIRECTORIES(${CLAR_PATH}) - FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/clar_helpers.c) + FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) + SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . - DEPENDS ${CLAR_PATH}/clar.suite ${SRC_TEST} + DEPENDS ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) - ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${CLAR_PATH}/main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) + SET_SOURCE_FILES_PROPERTIES( + ${CLAR_PATH}/clar/clar.c + PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite) + + ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) + TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES}) TARGET_OS_LIBRARIES(libgit2_clar) MSVC_SPLIT_SOURCES(libgit2_clar) diff --git a/tests-clar/clar b/tests-clar/clar index 1febaef17..fe7d9740b 160000 --- a/tests-clar/clar +++ b/tests-clar/clar @@ -1 +1 @@ -Subproject commit 1febaef178ccc12d3bdc4568a23f089b520a987b +Subproject commit fe7d9740becabac0e856eb0cdc19bc7e48680ba5 From a368fd0f7913a535903cca0bc1dccddefbfc7e89 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 20:08:49 +0100 Subject: [PATCH 04/37] Checkout test --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2cf252d9..2794bfa91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,6 +246,12 @@ IF (BUILD_CLAR) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") + ADD_CUSTOM_COMMAND( + COMMAND echo "###### testing this stuff" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS "${CLAR_PATH}/clar/clar.c" + ) + ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . From 0df4167577873cc91fd3745566195c46c009c59d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 21:22:19 +0100 Subject: [PATCH 05/37] Submodule checkout --- .travis.yml | 4 +--- CMakeLists.txt | 14 +++++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ce490356..e4e5a0b9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ # Travis-CI Build for libgit2 # see travis-ci.org for details - -# As CMake is not officially supported we use erlang VMs language: c compiler: @@ -28,7 +26,7 @@ script: - mkdir _build - cd _build - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS - - cmake --build . --target install + - cmake --build . --target submodules install - ctest -V . # Run Tests diff --git a/CMakeLists.txt b/CMakeLists.txt index 2794bfa91..dbb11d236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,6 +231,12 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_D INSTALL(DIRECTORY include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} ) INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) + +ADD_CUSTOM_TARGET( + submodules + COMMAND git submodule update --init tests-clar/clar +) + # Tests IF (BUILD_CLAR) FIND_PACKAGE(PythonInterp REQUIRED) @@ -243,15 +249,9 @@ IF (BUILD_CLAR) INCLUDE_DIRECTORIES(${CLAR_PATH}) FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) - SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c") + SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c" "${CLAR_PATH}/clar/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") - ADD_CUSTOM_COMMAND( - COMMAND echo "###### testing this stuff" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS "${CLAR_PATH}/clar/clar.c" - ) - ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . From e229c048255dfea78429cff6f5cc911987f5f8e5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 21:25:32 +0100 Subject: [PATCH 06/37] Fuck you CMake --- .travis.yml | 4 ++-- CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4e5a0b9f..507248a99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,8 +26,8 @@ script: - mkdir _build - cd _build - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS - - cmake --build . --target submodules install - - ctest -V . + - make submodules all + - ./libgit2_clar # Run Tests after_script: diff --git a/CMakeLists.txt b/CMakeLists.txt index dbb11d236..43b405d4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,6 +235,7 @@ INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) ADD_CUSTOM_TARGET( submodules COMMAND git submodule update --init tests-clar/clar + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # Tests From a44f2e9e7b2dbcdf51564453475ec9a684cf7f75 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 22:26:34 +0100 Subject: [PATCH 07/37] Try it like this... --- .travis.yml | 6 ++++-- CMakeLists.txt | 12 +++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 507248a99..8ce490356 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ # Travis-CI Build for libgit2 # see travis-ci.org for details + +# As CMake is not officially supported we use erlang VMs language: c compiler: @@ -26,8 +28,8 @@ script: - mkdir _build - cd _build - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS - - make submodules all - - ./libgit2_clar + - cmake --build . --target install + - ctest -V . # Run Tests after_script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 43b405d4b..2f5c559e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,13 +231,6 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc DESTINATION ${LIB_INSTALL_D INSTALL(DIRECTORY include/git2 DESTINATION ${INCLUDE_INSTALL_DIR} ) INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) - -ADD_CUSTOM_TARGET( - submodules - COMMAND git submodule update --init tests-clar/clar - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - # Tests IF (BUILD_CLAR) FIND_PACKAGE(PythonInterp REQUIRED) @@ -253,6 +246,11 @@ IF (BUILD_CLAR) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c" "${CLAR_PATH}/clar/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") + ADD_CUSTOM_COMMAND( + OUTPUT ${CLAR_PATH}/clar/clar.c + COMMAND git submodule update --init tests-clar/clar + ) + ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . From 39cd01779c84e0574c11f2e804f28c815e82a583 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jan 2013 22:38:10 +0100 Subject: [PATCH 08/37] This is a better name --- CMakeLists.txt | 3 ++- tests-clar/{clar_helpers.c => clar_libgit2.c} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename tests-clar/{clar_helpers.c => clar_libgit2.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f5c559e6..188678ca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,12 +243,13 @@ IF (BUILD_CLAR) INCLUDE_DIRECTORIES(${CLAR_PATH}) FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) - SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_helpers.c" "${CLAR_PATH}/clar/clar.c") + SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar/clar.c COMMAND git submodule update --init tests-clar/clar + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) ADD_CUSTOM_COMMAND( diff --git a/tests-clar/clar_helpers.c b/tests-clar/clar_libgit2.c similarity index 100% rename from tests-clar/clar_helpers.c rename to tests-clar/clar_libgit2.c From 6443eaf22f3567a430f038e8edc92e9f101db44d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 00:50:29 +0100 Subject: [PATCH 09/37] Disable Network suite by default --- CMakeLists.txt | 2 +- tests-clar/clar | 2 +- tests-clar/online/clone.c | 16 ++++++++-------- tests-clar/online/fetch.c | 14 +++++++------- tests-clar/online/fetchhead.c | 10 +++++----- tests-clar/online/push.c | 30 +++++++++++++++--------------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 188678ca0..39a2da6a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,7 +254,7 @@ IF (BUILD_CLAR) ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite - COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . + COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . -xonline DEPENDS ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) diff --git a/tests-clar/clar b/tests-clar/clar index fe7d9740b..3f99b7f36 160000 --- a/tests-clar/clar +++ b/tests-clar/clar @@ -1 +1 @@ -Subproject commit fe7d9740becabac0e856eb0cdc19bc7e48680ba5 +Subproject commit 3f99b7f36ffa2b0965eefd04abac998fa37ced23 diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index f783a5a8b..bf35fac04 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -10,7 +10,7 @@ static git_repository *g_repo; static git_remote *g_origin; static git_clone_options g_options; -void test_clone_network__initialize(void) +void test_online_clone__initialize(void) { g_repo = NULL; @@ -19,7 +19,7 @@ void test_clone_network__initialize(void) cl_git_pass(git_remote_new(&g_origin, NULL, "origin", LIVE_REPO_URL, GIT_REMOTE_DEFAULT_FETCH)); } -void test_clone_network__cleanup(void) +void test_online_clone__cleanup(void) { git_remote_free(g_origin); } @@ -34,7 +34,7 @@ static void cleanup_repository(void *path) } -void test_clone_network__network_full(void) +void test_online_clone__network_full(void) { git_remote *origin; @@ -48,7 +48,7 @@ void test_clone_network__network_full(void) } -void test_clone_network__network_bare(void) +void test_online_clone__network_bare(void) { git_remote *origin; @@ -62,7 +62,7 @@ void test_clone_network__network_bare(void) git_remote_free(origin); } -void test_clone_network__cope_with_already_existing_directory(void) +void test_online_clone__cope_with_already_existing_directory(void) { cl_set_cleanup(&cleanup_repository, "./foo"); @@ -70,7 +70,7 @@ void test_clone_network__cope_with_already_existing_directory(void) cl_git_pass(git_clone(&g_repo, g_origin, "./foo", &g_options)); } -void test_clone_network__empty_repository(void) +void test_online_clone__empty_repository(void) { git_reference *head; @@ -91,7 +91,7 @@ void test_clone_network__empty_repository(void) git_reference_free(head); } -void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) +void test_online_clone__can_prevent_the_checkout_of_a_standard_repo(void) { git_buf path = GIT_BUF_INIT; cl_set_cleanup(&cleanup_repository, "./foo"); @@ -118,7 +118,7 @@ static void fetch_progress(const git_transfer_progress *stats, void *payload) (*was_called) = true; } -void test_clone_network__can_checkout_a_cloned_repo(void) +void test_online_clone__can_checkout_a_cloned_repo(void) { git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; git_buf path = GIT_BUF_INIT; diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index 979b02303..6fcea2512 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -3,12 +3,12 @@ static git_repository *_repo; static int counter; -void test_network_fetch__initialize(void) +void test_online_fetch__initialize(void) { cl_git_pass(git_repository_init(&_repo, "./fetch", 0)); } -void test_network_fetch__cleanup(void) +void test_online_fetch__cleanup(void) { git_repository_free(_repo); _repo = NULL; @@ -53,22 +53,22 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) git_remote_free(remote); } -void test_network_fetch__default_git(void) +void test_online_fetch__default_git(void) { do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } -void test_network_fetch__default_http(void) +void test_online_fetch__default_http(void) { do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } -void test_network_fetch__no_tags_git(void) +void test_online_fetch__no_tags_git(void) { do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); } -void test_network_fetch__no_tags_http(void) +void test_online_fetch__no_tags_http(void) { do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); } @@ -81,7 +81,7 @@ static void transferProgressCallback(const git_transfer_progress *stats, void *p *invoked = true; } -void test_network_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) +void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) { git_repository *_repository; bool invoked = false; diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c index a6b8a6ffd..fb6cf57e5 100644 --- a/tests-clar/online/fetchhead.c +++ b/tests-clar/online/fetchhead.c @@ -11,7 +11,7 @@ static git_repository *g_repo; static git_remote *g_origin; static git_clone_options g_options; -void test_fetchhead_network__initialize(void) +void test_online_fetchhead__initialize(void) { g_repo = NULL; @@ -20,7 +20,7 @@ void test_fetchhead_network__initialize(void) cl_git_pass(git_remote_new(&g_origin, NULL, "origin", LIVE_REPO_URL, GIT_REMOTE_DEFAULT_FETCH)); } -void test_fetchhead_network__cleanup(void) +void test_online_fetchhead__cleanup(void) { git_remote_free(g_origin); } @@ -70,19 +70,19 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet cl_assert(equals); } -void test_fetchhead_network__wildcard_spec(void) +void test_online_fetchhead__wildcard_spec(void) { fetchhead_test_clone(); fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA); } -void test_fetchhead_network__explicit_spec(void) +void test_online_fetchhead__explicit_spec(void) { fetchhead_test_clone(); fetchhead_test_fetch("refs/heads/first-merge:refs/remotes/origin/first-merge", FETCH_HEAD_EXPLICIT_DATA); } -void test_fetchhead_network__no_merges(void) +void test_online_fetchhead__no_merges(void) { git_config *config; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 8878e6356..477a39ee6 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -125,7 +125,7 @@ static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t git_vector_free(&actual_refs); } -void test_network_push__initialize(void) +void test_online_push__initialize(void) { git_vector delete_specs = GIT_VECTOR_INIT; size_t i; @@ -205,7 +205,7 @@ void test_network_push__initialize(void) printf("GITTEST_REMOTE_URL unset; skipping push test\n"); } -void test_network_push__cleanup(void) +void test_online_push__cleanup(void) { if (_remote) git_remote_free(_remote); @@ -269,12 +269,12 @@ static void do_push(const char *refspecs[], size_t refspecs_len, } /* Call push_finish() without ever calling git_push_add_refspec() */ -void test_network_push__noop(void) +void test_online_push__noop(void) { do_push(NULL, 0, NULL, 0, NULL, 0, 0); } -void test_network_push__b1(void) +void test_online_push__b1(void) { const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; push_status exp_stats[] = { { "refs/heads/b1", NULL } }; @@ -284,7 +284,7 @@ void test_network_push__b1(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__b2(void) +void test_online_push__b2(void) { const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; push_status exp_stats[] = { { "refs/heads/b2", NULL } }; @@ -294,7 +294,7 @@ void test_network_push__b2(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__b3(void) +void test_online_push__b3(void) { const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; push_status exp_stats[] = { { "refs/heads/b3", NULL } }; @@ -304,7 +304,7 @@ void test_network_push__b3(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__b4(void) +void test_online_push__b4(void) { const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; push_status exp_stats[] = { { "refs/heads/b4", NULL } }; @@ -314,7 +314,7 @@ void test_network_push__b4(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__b5(void) +void test_online_push__b5(void) { const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; push_status exp_stats[] = { { "refs/heads/b5", NULL } }; @@ -324,7 +324,7 @@ void test_network_push__b5(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__multi(void) +void test_online_push__multi(void) { const char *specs[] = { "refs/heads/b1:refs/heads/b1", @@ -352,7 +352,7 @@ void test_network_push__multi(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } -void test_network_push__implicit_tgt(void) +void test_online_push__implicit_tgt(void) { const char *specs1[] = { "refs/heads/b1:" }; push_status exp_stats1[] = { { "refs/heads/b1", NULL } }; @@ -373,7 +373,7 @@ void test_network_push__implicit_tgt(void) exp_refs2, ARRAY_SIZE(exp_refs2), 0); } -void test_network_push__fast_fwd(void) +void test_online_push__fast_fwd(void) { /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ @@ -407,7 +407,7 @@ void test_network_push__fast_fwd(void) exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0); } -void test_network_push__force(void) +void test_online_push__force(void) { const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; push_status exp_stats1[] = { { "refs/heads/tgt", NULL } }; @@ -433,7 +433,7 @@ void test_network_push__force(void) exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0); } -void test_network_push__delete(void) +void test_online_push__delete(void) { const char *specs1[] = { "refs/heads/b1:refs/heads/tgt1", @@ -486,7 +486,7 @@ void test_network_push__delete(void) exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0); } -void test_network_push__bad_refspecs(void) +void test_online_push__bad_refspecs(void) { /* All classes of refspecs that should be rejected by * git_push_add_refspec() should go in this test. @@ -504,7 +504,7 @@ void test_network_push__bad_refspecs(void) } } -void test_network_push__expressions(void) +void test_online_push__expressions(void) { /* TODO: Expressions in refspecs doesn't actually work yet */ const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; From ad27838bdc5b9d8d7730c36b24b5a519a3e5ec6e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 00:58:46 +0100 Subject: [PATCH 10/37] Proper submodule dependency --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39a2da6a4..7310eb61d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,8 +246,8 @@ IF (BUILD_CLAR) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") - ADD_CUSTOM_COMMAND( - OUTPUT ${CLAR_PATH}/clar/clar.c + ADD_CUSTOM_TARGET( + clar_submodule COMMAND git submodule update --init tests-clar/clar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -255,7 +255,7 @@ IF (BUILD_CLAR) ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . -xonline - DEPENDS ${SRC_TEST} + DEPENDS clar_submodule ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) From 39444bea0a3ad2946cb9772c5253d3db40bf813b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 01:01:03 +0100 Subject: [PATCH 11/37] ...fine --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7310eb61d..099ceefbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,7 +247,7 @@ IF (BUILD_CLAR) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_TARGET( - clar_submodule + clar_submodule ALL COMMAND git submodule update --init tests-clar/clar WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -255,7 +255,7 @@ IF (BUILD_CLAR) ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . -xonline - DEPENDS clar_submodule ${SRC_TEST} + DEPENDS ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) From afb181167ede0676b4a7bad5972cc712c3da1c17 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 01:04:18 +0100 Subject: [PATCH 12/37] /deal with it --- .travis.yml | 1 + CMakeLists.txt | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ce490356..2827fdbfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ install: # Run the Build script script: + - git submodule update --init tests-clar/clar - mkdir _build - cd _build - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS diff --git a/CMakeLists.txt b/CMakeLists.txt index 099ceefbe..dbde281e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,12 +246,6 @@ IF (BUILD_CLAR) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") - ADD_CUSTOM_TARGET( - clar_submodule ALL - COMMAND git submodule update --init tests-clar/clar - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . -xonline From f46769e52a907ca3b11acf598c9837f37d82cea4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 02:13:37 +0100 Subject: [PATCH 13/37] Fix network suite --- tests-clar/clar | 2 +- tests-clar/clone/nonetwork.c | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/tests-clar/clar b/tests-clar/clar index 3f99b7f36..75254eeb0 160000 --- a/tests-clar/clar +++ b/tests-clar/clar @@ -1 +1 @@ -Subproject commit 3f99b7f36ffa2b0965eefd04abac998fa37ced23 +Subproject commit 75254eeb042e8a6f83775c452b2b59da20e50bda diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 623a0683f..91c020e9f 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -19,18 +19,14 @@ void test_clone_nonetwork__initialize(void) } void test_clone_nonetwork__cleanup(void) -{ - git_remote_free(g_origin); -} - -static void cleanup_repository(void *path) { if (g_repo) { git_repository_free(g_repo); g_repo = NULL; } - cl_fixture_cleanup((const char *)path); + cl_fixture_cleanup("./foo"); + git_remote_free(g_origin); } void test_clone_nonetwork__bad_url(void) @@ -48,7 +44,6 @@ void test_clone_nonetwork__bad_url(void) void test_clone_nonetwork__local(void) { - cl_set_cleanup(&cleanup_repository, "./foo"); cl_git_pass(git_clone(&g_repo, g_origin, "./foo", &g_options)); } @@ -56,32 +51,25 @@ void test_clone_nonetwork__local_absolute_path(void) { const char *local_src = cl_fixture("testrepo.git"); git_remote_free(g_origin); + cl_git_pass(git_remote_new(&g_origin, NULL, "origin", local_src, GIT_REMOTE_DEFAULT_FETCH)); - - cl_set_cleanup(&cleanup_repository, "./foo"); - cl_git_pass(git_clone(&g_repo, g_origin, "./foo", &g_options)); } void test_clone_nonetwork__local_bare(void) { - cl_set_cleanup(&cleanup_repository, "./foo"); g_options.bare = true; cl_git_pass(git_clone(&g_repo, g_origin, "./foo", &g_options)); } void test_clone_nonetwork__fail_when_the_target_is_a_file(void) { - cl_set_cleanup(&cleanup_repository, "./foo"); - cl_git_mkfile("./foo", "Bar!"); cl_git_fail(git_clone(&g_repo, g_origin, "./foo", &g_options)); } void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) { - cl_set_cleanup(&cleanup_repository, "./foo"); - p_mkdir("./foo", GIT_DIR_MODE); cl_git_mkfile("./foo/bar", "Baz!"); cl_git_fail(git_clone(&g_repo, g_origin, "./foo", &g_options)); From 8ee7174be9bbb451c5dbcc06e5422e915fe08753 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 02:22:42 +0100 Subject: [PATCH 14/37] Remove the clar submodule --- .gitmodules | 3 --- tests-clar/clar | 1 - 2 files changed, 4 deletions(-) delete mode 100644 .gitmodules delete mode 160000 tests-clar/clar diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5d7eda9ac..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tests-clar/clar"] - path = tests-clar/clar - url = https://github.com/vmg/clar.git diff --git a/tests-clar/clar b/tests-clar/clar deleted file mode 160000 index 75254eeb0..000000000 --- a/tests-clar/clar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75254eeb042e8a6f83775c452b2b59da20e50bda From 2e6f06a8d47f4474bb3f268e66c040781a9a4ce2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 02:34:45 +0100 Subject: [PATCH 15/37] ...and add Clar raw --- CMakeLists.txt | 6 +- tests-clar/clar.c | 408 +++++++++++++++++++++++++++++++++++++ tests-clar/clar.h | 70 +++++++ tests-clar/clar/fixtures.h | 38 ++++ tests-clar/clar/fs.h | 325 +++++++++++++++++++++++++++++ tests-clar/clar/print.h | 59 ++++++ tests-clar/clar/sandbox.h | 127 ++++++++++++ tests-clar/clar_libgit2.h | 2 +- tests-clar/generate.py | 237 +++++++++++++++++++++ 9 files changed, 1268 insertions(+), 4 deletions(-) create mode 100644 tests-clar/clar.c create mode 100644 tests-clar/clar.h create mode 100644 tests-clar/clar/fixtures.h create mode 100644 tests-clar/clar/fs.h create mode 100644 tests-clar/clar/print.h create mode 100644 tests-clar/clar/sandbox.h create mode 100644 tests-clar/generate.py diff --git a/CMakeLists.txt b/CMakeLists.txt index dbde281e4..a0862a082 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,18 +243,18 @@ IF (BUILD_CLAR) INCLUDE_DIRECTORIES(${CLAR_PATH}) FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) - SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar/clar.c") + SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar.c") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite - COMMAND ${PYTHON_EXECUTABLE} clar/generate.py . -xonline + COMMAND ${PYTHON_EXECUTABLE} generate.py -xonline . DEPENDS ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) SET_SOURCE_FILES_PROPERTIES( - ${CLAR_PATH}/clar/clar.c + ${CLAR_PATH}/clar.c PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite) ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) diff --git a/tests-clar/clar.c b/tests-clar/clar.c new file mode 100644 index 000000000..a7d8d30d0 --- /dev/null +++ b/tests-clar/clar.c @@ -0,0 +1,408 @@ +#include +#include +#include +#include +#include +#include +#include + +/* required for sandboxing */ +#include +#include + +#ifdef _WIN32 +# include +# include +# include +# include + +# define _MAIN_CC __cdecl + +# define stat(path, st) _stat(path, st) +# define mkdir(path, mode) _mkdir(path) +# define chdir(path) _chdir(path) +# define access(path, mode) _access(path, mode) +# define strdup(str) _strdup(str) +# define strcasecmp(a,b) _stricmp(a,b) + +# ifndef __MINGW32__ +# pragma comment(lib, "shell32") +# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) +# define W_OK 02 +# define S_ISDIR(x) ((x & _S_IFDIR) != 0) +# define snprint_eq(buf,sz,fmt,a,b) _snprintf_s(buf,sz,_TRUNCATE,fmt,a,b) +# else +# define snprint_eq snprintf +# endif + typedef struct _stat STAT_T; +#else +# include /* waitpid(2) */ +# include +# define _MAIN_CC +# define snprint_eq snprintf + typedef struct stat STAT_T; +#endif + +#include "clar.h" + +static void fs_rm(const char *_source); +static void fs_copy(const char *_source, const char *dest); + +static const char * +fixture_path(const char *base, const char *fixture_name); + +struct clar_error { + const char *test; + int test_number; + const char *suite; + const char *file; + int line_number; + const char *error_msg; + char *description; + + struct clar_error *next; +}; + +static struct { + const char *active_test; + const char *active_suite; + + int suite_errors; + int total_errors; + + int tests_ran; + int suites_ran; + + int report_errors_only; + int exit_on_error; + + struct clar_error *errors; + struct clar_error *last_error; + + void (*local_cleanup)(void *); + void *local_cleanup_payload; + + jmp_buf trampoline; + int trampoline_enabled; +} _clar; + +struct clar_func { + const char *name; + void (*ptr)(void); +}; + +struct clar_suite { + const char *name; + struct clar_func initialize; + struct clar_func cleanup; + const struct clar_func *tests; + size_t test_count; + int enabled; +}; + +/* From clar_print_*.c */ +static void clar_print_init(int test_count, int suite_count, const char *suite_names); +static void clar_print_shutdown(int test_count, int suite_count, int error_count); +static void clar_print_error(int num, const struct clar_error *error); +static void clar_print_ontest(const char *test_name, int test_number, int failed); +static void clar_print_onsuite(const char *suite_name, int suite_index); +static void clar_print_onabort(const char *msg, ...); + +/* From clar_sandbox.c */ +static void clar_unsandbox(void); +static int clar_sandbox(void); + +/* Load the declarations for the test suite */ +#include "clar.suite" + +/* Core test functions */ +static void +clar_report_errors(void) +{ + int i = 1; + struct clar_error *error, *next; + + error = _clar.errors; + while (error != NULL) { + next = error->next; + clar_print_error(i++, error); + free(error->description); + free(error); + error = next; + } + + _clar.errors = _clar.last_error = NULL; +} + +static void +clar_run_test( + const struct clar_func *test, + const struct clar_func *initialize, + const struct clar_func *cleanup) +{ + int error_st = _clar.suite_errors; + + _clar.trampoline_enabled = 1; + + if (setjmp(_clar.trampoline) == 0) { + if (initialize->ptr != NULL) + initialize->ptr(); + + test->ptr(); + } + + _clar.trampoline_enabled = 0; + + if (_clar.local_cleanup != NULL) + _clar.local_cleanup(_clar.local_cleanup_payload); + + if (cleanup->ptr != NULL) + cleanup->ptr(); + + _clar.tests_ran++; + + /* remove any local-set cleanup methods */ + _clar.local_cleanup = NULL; + _clar.local_cleanup_payload = NULL; + + if (_clar.report_errors_only) + clar_report_errors(); + else + clar_print_ontest( + test->name, + _clar.tests_ran, + (_clar.suite_errors > error_st) + ); +} + +static void +clar_run_suite(const struct clar_suite *suite) +{ + const struct clar_func *test = suite->tests; + size_t i; + + if (!suite->enabled) + return; + + if (_clar.exit_on_error && _clar.total_errors) + return; + + if (!_clar.report_errors_only) + clar_print_onsuite(suite->name, ++_clar.suites_ran); + + _clar.active_suite = suite->name; + _clar.suite_errors = 0; + + for (i = 0; i < suite->test_count; ++i) { + _clar.active_test = test[i].name; + clar_run_test(&test[i], &suite->initialize, &suite->cleanup); + + if (_clar.exit_on_error && _clar.total_errors) + return; + } +} + +static void +clar_usage(const char *arg) +{ + printf("Usage: %s [options]\n\n", arg); + printf("Options:\n"); + printf(" -sname\t\tRun only the suite with `name`\n"); + printf(" -iname\t\tInclude the suite with `name`\n"); + printf(" -xname\t\tExclude the suite with `name`\n"); + printf(" -q \t\tOnly report tests that had an error\n"); + printf(" -Q \t\tQuit as soon as a test fails\n"); + printf(" -l \t\tPrint suite names\n"); + exit(-1); +} + +static void +clar_parse_args(int argc, char **argv) +{ + int i; + + for (i = 1; i < argc; ++i) { + char *argument = argv[i]; + + if (argument[0] != '-') + clar_usage(argv[0]); + + switch (argument[1]) { + case 's': + case 'i': + case 'x': { /* given suite name */ + int offset = (argument[2] == '=') ? 3 : 2; + char action = argument[1]; + size_t j, len; + + argument += offset; + len = strlen(argument); + + if (len == 0) + clar_usage(argv[0]); + + for (j = 0; j < _clar_suite_count; ++j) { + if (strncmp(argument, _clar_suites[j].name, len) == 0) { + switch (action) { + case 's': clar_run_suite(&_clar_suites[j]); break; + case 'i': _clar_suites[j].enabled = 1; break; + case 'x': _clar_suites[j].enabled = 0; break; + } + break; + } + } + + if (j == _clar_suite_count) { + clar_print_onabort("No suite matching '%s' found.\n", argument); + exit(-1); + } + break; + } + + case 'q': + _clar.report_errors_only = 1; + break; + + case 'Q': + _clar.exit_on_error = 1; + break; + + case 'l': { + size_t j; + printf("Test suites (use -s to run just one):\n"); + for (j = 0; j < _clar_suite_count; ++j) + printf(" %3d: %s\n", (int)j, _clar_suites[j].name); + + exit(0); + } + + default: + clar_usage(argv[0]); + } + } +} + +int +clar_test(int argc, char **argv) +{ + clar_print_init( + (int)_clar_callback_count, + (int)_clar_suite_count, + "" + ); + + if (clar_sandbox() < 0) { + clar_print_onabort("Failed to sandbox the test runner.\n"); + exit(-1); + } + + if (argc > 1) + clar_parse_args(argc, argv); + + if (!_clar.suites_ran) { + size_t i; + for (i = 0; i < _clar_suite_count; ++i) + clar_run_suite(&_clar_suites[i]); + } + + clar_print_shutdown( + _clar.tests_ran, + (int)_clar_suite_count, + _clar.total_errors + ); + + clar_unsandbox(); + return _clar.total_errors; +} + +void +clar__assert( + int condition, + const char *file, + int line, + const char *error_msg, + const char *description, + int should_abort) +{ + struct clar_error *error; + + if (condition) + return; + + error = calloc(1, sizeof(struct clar_error)); + + if (_clar.errors == NULL) + _clar.errors = error; + + if (_clar.last_error != NULL) + _clar.last_error->next = error; + + _clar.last_error = error; + + error->test = _clar.active_test; + error->test_number = _clar.tests_ran; + error->suite = _clar.active_suite; + error->file = file; + error->line_number = line; + error->error_msg = error_msg; + + if (description != NULL) + error->description = strdup(description); + + _clar.suite_errors++; + _clar.total_errors++; + + if (should_abort) { + if (!_clar.trampoline_enabled) { + clar_print_onabort( + "Fatal error: a cleanup method raised an exception."); + clar_report_errors(); + exit(-1); + } + + longjmp(_clar.trampoline, -1); + } +} + +void clar__assert_equal_s( + const char *s1, + const char *s2, + const char *file, + int line, + const char *err, + int should_abort) +{ + int match = (s1 == NULL || s2 == NULL) ? (s1 == s2) : (strcmp(s1, s2) == 0); + + if (!match) { + char buf[4096]; + snprint_eq(buf, 4096, "'%s' != '%s'", s1, s2); + clar__assert(0, file, line, err, buf, should_abort); + } +} + +void clar__assert_equal_i( + int i1, + int i2, + const char *file, + int line, + const char *err, + int should_abort) +{ + if (i1 != i2) { + char buf[128]; + snprint_eq(buf, 128, "%d != %d", i1, i2); + clar__assert(0, file, line, err, buf, should_abort); + } +} + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque) +{ + _clar.local_cleanup = cleanup; + _clar.local_cleanup_payload = opaque; +} + +#include "clar/sandbox.h" +#include "clar/fixtures.h" +#include "clar/fs.h" +#include "clar/print.h" diff --git a/tests-clar/clar.h b/tests-clar/clar.h new file mode 100644 index 000000000..825874116 --- /dev/null +++ b/tests-clar/clar.h @@ -0,0 +1,70 @@ +#ifndef __CLAR_TEST_H__ +#define __CLAR_TEST_H__ + +#include + +int clar_test(int argc, char *argv[]); + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque); +void cl_fs_cleanup(void); + +#ifdef CLAR_FIXTURE_PATH +const char *cl_fixture(const char *fixture_name); +void cl_fixture_sandbox(const char *fixture_name); +void cl_fixture_cleanup(const char *fixture_name); +#endif + +/** + * Assertion macros with explicit error message + */ +#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1) +#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1) +#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 1) + +/** + * Check macros with explicit error message + */ +#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 0) +#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0) +#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 0) + +/** + * Assertion macros with no error message + */ +#define cl_must_pass(expr) cl_must_pass_(expr, NULL) +#define cl_must_fail(expr) cl_must_fail_(expr, NULL) +#define cl_assert(expr) cl_assert_(expr, NULL) + +/** + * Check macros with no error message + */ +#define cl_check_pass(expr) cl_check_pass_(expr, NULL) +#define cl_check_fail(expr) cl_check_fail_(expr, NULL) +#define cl_check(expr) cl_check_(expr, NULL) + +/** + * Forced failure/warning + */ +#define cl_fail(desc) clar__assert(0, __FILE__, __LINE__, "Test failed.", desc, 1) +#define cl_warning(desc) clar__assert(0, __FILE__, __LINE__, "Warning during test execution:", desc, 0) + +/** + * Typed assertion macros + */ +#define cl_assert_equal_s(s1,s2) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1) +#define cl_assert_equal_i(i1,i2) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2, 1) +#define cl_assert_equal_b(b1,b2) clar__assert_equal_i(!!(b1),!!(b2),__FILE__,__LINE__,#b1 " != " #b2, 1) +#define cl_assert_equal_p(p1,p2) cl_assert((p1) == (p2)) + +void clar__assert( + int condition, + const char *file, + int line, + const char *error, + const char *description, + int should_abort); + +void clar__assert_equal_s(const char *,const char *,const char *,int,const char *,int); +void clar__assert_equal_i(int,int,const char *,int,const char *,int); + +#endif diff --git a/tests-clar/clar/fixtures.h b/tests-clar/clar/fixtures.h new file mode 100644 index 000000000..264cd7f4f --- /dev/null +++ b/tests-clar/clar/fixtures.h @@ -0,0 +1,38 @@ +static const char * +fixture_path(const char *base, const char *fixture_name) +{ + static char _path[4096]; + size_t root_len; + + root_len = strlen(base); + strncpy(_path, base, sizeof(_path)); + + if (_path[root_len - 1] != '/') + _path[root_len++] = '/'; + + if (fixture_name[0] == '/') + fixture_name++; + + strncpy(_path + root_len, + fixture_name, + sizeof(_path) - root_len); + + return _path; +} + +#ifdef CLAR_FIXTURE_PATH +const char *cl_fixture(const char *fixture_name) +{ + return fixture_path(CLAR_FIXTURE_PATH, fixture_name); +} + +void cl_fixture_sandbox(const char *fixture_name) +{ + fs_copy(cl_fixture(fixture_name), _clar_path); +} + +void cl_fixture_cleanup(const char *fixture_name) +{ + fs_rm(fixture_path(_clar_path, fixture_name)); +} +#endif diff --git a/tests-clar/clar/fs.h b/tests-clar/clar/fs.h new file mode 100644 index 000000000..1cdc1ce2f --- /dev/null +++ b/tests-clar/clar/fs.h @@ -0,0 +1,325 @@ +#ifdef _WIN32 + +#define RM_RETRY_COUNT 5 +#define RM_RETRY_DELAY 10 + +#ifdef __MINGW32__ + +/* These security-enhanced functions are not available + * in MinGW, so just use the vanilla ones */ +#define wcscpy_s(a, b, c) wcscpy((a), (c)) +#define wcscat_s(a, b, c) wcscat((a), (c)) + +#endif /* __MINGW32__ */ + +static int +fs__dotordotdot(WCHAR *_tocheck) +{ + return _tocheck[0] == '.' && + (_tocheck[1] == '\0' || + (_tocheck[1] == '.' && _tocheck[2] == '\0')); +} + +static int +fs_rmdir_rmdir(WCHAR *_wpath) +{ + unsigned retries = 1; + + while (!RemoveDirectoryW(_wpath)) { + /* Only retry when we have retries remaining, and the + * error was ERROR_DIR_NOT_EMPTY. */ + if (retries++ > RM_RETRY_COUNT || + ERROR_DIR_NOT_EMPTY != GetLastError()) + return -1; + + /* Give whatever has a handle to a child item some time + * to release it before trying again */ + Sleep(RM_RETRY_DELAY * retries * retries); + } + + return 0; +} + +static void +fs_rmdir_helper(WCHAR *_wsource) +{ + WCHAR buffer[MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + int buffer_prefix_len; + + /* Set up the buffer and capture the length */ + wcscpy_s(buffer, MAX_PATH, _wsource); + wcscat_s(buffer, MAX_PATH, L"\\"); + buffer_prefix_len = wcslen(buffer); + + /* FindFirstFile needs a wildcard to match multiple items */ + wcscat_s(buffer, MAX_PATH, L"*"); + find_handle = FindFirstFileW(buffer, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_rmdir_helper(buffer); + else { + /* If set, the +R bit must be cleared before deleting */ + if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes) + cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(buffer)); + } + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); + + /* Now that the directory is empty, remove it */ + cl_assert(0 == fs_rmdir_rmdir(_wsource)); +} + +static int +fs_rm_wait(WCHAR *_wpath) +{ + unsigned retries = 1; + DWORD last_error; + + do { + if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath)) + last_error = GetLastError(); + else + last_error = ERROR_SUCCESS; + + /* Is the item gone? */ + if (ERROR_FILE_NOT_FOUND == last_error || + ERROR_PATH_NOT_FOUND == last_error) + return 0; + + Sleep(RM_RETRY_DELAY * retries * retries); + } + while (retries++ <= RM_RETRY_COUNT); + + return -1; +} + +static void +fs_rm(const char *_source) +{ + WCHAR wsource[MAX_PATH]; + DWORD attrs; + + /* The input path is UTF-8. Convert it to wide characters + * for use with the Windows API */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, /* Indicates NULL termination */ + wsource, + MAX_PATH)); + + /* Does the item exist? If not, we have no work to do */ + attrs = GetFileAttributesW(wsource); + + if (INVALID_FILE_ATTRIBUTES == attrs) + return; + + if (FILE_ATTRIBUTE_DIRECTORY & attrs) + fs_rmdir_helper(wsource); + else { + /* The item is a file. Strip the +R bit */ + if (FILE_ATTRIBUTE_READONLY & attrs) + cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(wsource)); + } + + /* Wait for the DeleteFile or RemoveDirectory call to complete */ + cl_assert(0 == fs_rm_wait(wsource)); +} + +static void +fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest) +{ + WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + int buf_source_prefix_len, buf_dest_prefix_len; + + wcscpy_s(buf_source, MAX_PATH, _wsource); + wcscat_s(buf_source, MAX_PATH, L"\\"); + buf_source_prefix_len = wcslen(buf_source); + + wcscpy_s(buf_dest, MAX_PATH, _wdest); + wcscat_s(buf_dest, MAX_PATH, L"\\"); + buf_dest_prefix_len = wcslen(buf_dest); + + /* Get an enumerator for the items in the source. */ + wcscat_s(buf_source, MAX_PATH, L"*"); + find_handle = FindFirstFileW(buf_source, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + /* Create the target directory. */ + cl_assert(CreateDirectoryW(_wdest, NULL)); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName); + wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_copydir_helper(buf_source, buf_dest); + else + cl_assert(CopyFileW(buf_source, buf_dest, TRUE)); + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); +} + +static void +fs_copy(const char *_source, const char *_dest) +{ + WCHAR wsource[MAX_PATH], wdest[MAX_PATH]; + DWORD source_attrs, dest_attrs; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + + /* The input paths are UTF-8. Convert them to wide characters + * for use with the Windows API. */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, + wsource, + MAX_PATH)); + + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _dest, + -1, + wdest, + MAX_PATH)); + + /* Check the source for existence */ + source_attrs = GetFileAttributesW(wsource); + cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs); + + /* Check the target for existence */ + dest_attrs = GetFileAttributesW(wdest); + + if (INVALID_FILE_ATTRIBUTES != dest_attrs) { + /* Target exists; append last path part of source to target. + * Use FindFirstFile to parse the path */ + find_handle = FindFirstFileW(wsource, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + wcscat_s(wdest, MAX_PATH, L"\\"); + wcscat_s(wdest, MAX_PATH, find_data.cFileName); + FindClose(find_handle); + + /* Check the new target for existence */ + cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest)); + } + + if (FILE_ATTRIBUTE_DIRECTORY & source_attrs) + fs_copydir_helper(wsource, wdest); + else + cl_assert(CopyFileW(wsource, wdest, TRUE)); +} + +void +cl_fs_cleanup(void) +{ + fs_rm(fixture_path(_clar_path, "*")); +} + +#else +static int +shell_out(char * const argv[]) +{ + int status; + pid_t pid; + + pid = fork(); + + if (pid < 0) { + fprintf(stderr, + "System error: `fork()` call failed.\n"); + exit(-1); + } + + if (pid == 0) { + execv(argv[0], argv); + } + + waitpid(pid, &status, 0); + return WEXITSTATUS(status); +} + +static void +fs_copy(const char *_source, const char *dest) +{ + char *argv[5]; + char *source; + size_t source_len; + + source = strdup(_source); + source_len = strlen(source); + + if (source[source_len - 1] == '/') + source[source_len - 1] = 0; + + argv[0] = "/bin/cp"; + argv[1] = "-R"; + argv[2] = source; + argv[3] = (char *)dest; + argv[4] = NULL; + + cl_must_pass_( + shell_out(argv), + "Failed to copy test fixtures to sandbox" + ); + + free(source); +} + +static void +fs_rm(const char *source) +{ + char *argv[4]; + + argv[0] = "/bin/rm"; + argv[1] = "-Rf"; + argv[2] = (char *)source; + argv[3] = NULL; + + cl_must_pass_( + shell_out(argv), + "Failed to cleanup the sandbox" + ); +} + +void +cl_fs_cleanup(void) +{ + clar_unsandbox(); + clar_sandbox(); +} +#endif diff --git a/tests-clar/clar/print.h b/tests-clar/clar/print.h new file mode 100644 index 000000000..db9da9198 --- /dev/null +++ b/tests-clar/clar/print.h @@ -0,0 +1,59 @@ + +static void clar_print_init(int test_count, int suite_count, const char *suite_names) +{ + (void)test_count; + printf("Loaded %d suites: %s\n", (int)suite_count, suite_names); + printf("Started\n"); +} + +static void clar_print_shutdown(int test_count, int suite_count, int error_count) +{ + (void)test_count; + (void)suite_count; + (void)error_count; + + printf("\n\n"); + clar_report_errors(); +} + +static void clar_print_error(int num, const struct clar_error *error) +{ + printf(" %d) Failure:\n", num); + + printf("%s::%s [%s:%d]\n", + error->suite, + error->test, + error->file, + error->line_number); + + printf(" %s\n", error->error_msg); + + if (error->description != NULL) + printf(" %s\n", error->description); + + printf("\n"); + fflush(stdout); +} + +static void clar_print_ontest(const char *test_name, int test_number, int failed) +{ + (void)test_name; + (void)test_number; + printf("%c", failed ? 'F' : '.'); + fflush(stdout); +} + +static void clar_print_onsuite(const char *suite_name, int suite_index) +{ + /* noop */ + (void)suite_index; + (void)suite_name; +} + +static void clar_print_onabort(const char *msg, ...) +{ + va_list argp; + va_start(argp, msg); + vfprintf(stderr, msg, argp); + va_end(argp); +} diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h new file mode 100644 index 000000000..bed3011fe --- /dev/null +++ b/tests-clar/clar/sandbox.h @@ -0,0 +1,127 @@ +static char _clar_path[4096]; + +static int +is_valid_tmp_path(const char *path) +{ + STAT_T st; + + if (stat(path, &st) != 0) + return 0; + + if (!S_ISDIR(st.st_mode)) + return 0; + + return (access(path, W_OK) == 0); +} + +static int +find_tmp_path(char *buffer, size_t length) +{ +#ifndef _WIN32 + static const size_t var_count = 4; + static const char *env_vars[] = { + "TMPDIR", "TMP", "TEMP", "USERPROFILE" + }; + + size_t i; + + for (i = 0; i < var_count; ++i) { + const char *env = getenv(env_vars[i]); + if (!env) + continue; + + if (is_valid_tmp_path(env)) { + strncpy(buffer, env, length); + return 0; + } + } + + /* If the environment doesn't say anything, try to use /tmp */ + if (is_valid_tmp_path("/tmp")) { + strncpy(buffer, "/tmp", length); + return 0; + } + +#else + if (GetTempPath((DWORD)length, buffer)) + return 0; +#endif + + /* This system doesn't like us, try to use the current directory */ + if (is_valid_tmp_path(".")) { + strncpy(buffer, ".", length); + return 0; + } + + return -1; +} + +static void clar_unsandbox(void) +{ + if (_clar_path[0] == '\0') + return; + +#ifdef _WIN32 + chdir(".."); +#endif + + fs_rm(_clar_path); +} + +static int build_sandbox_path(void) +{ + const char path_tail[] = "clar_tmp_XXXXXX"; + size_t len; + + if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0) + return -1; + + len = strlen(_clar_path); + +#ifdef _WIN32 + { /* normalize path to POSIX forward slashes */ + size_t i; + for (i = 0; i < len; ++i) { + if (_clar_path[i] == '\\') + _clar_path[i] = '/'; + } + } +#endif + + if (_clar_path[len - 1] != '/') { + _clar_path[len++] = '/'; + } + + strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len); + +#if defined(__MINGW32__) + if (_mktemp(_clar_path) == NULL) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#elif defined(_WIN32) + if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#else + if (mkdtemp(_clar_path) == NULL) + return -1; +#endif + + return 0; +} + +static int clar_sandbox(void) +{ + if (_clar_path[0] == '\0' && build_sandbox_path() < 0) + return -1; + + if (chdir(_clar_path) != 0) + return -1; + + return 0; +} + diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 15b5daaf3..91a542654 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -1,7 +1,7 @@ #ifndef __CLAR_LIBGIT2__ #define __CLAR_LIBGIT2__ -#include "clar/clar.h" +#include "clar.h" #include #include "common.h" diff --git a/tests-clar/generate.py b/tests-clar/generate.py new file mode 100644 index 000000000..74b69bda3 --- /dev/null +++ b/tests-clar/generate.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python + +from __future__ import with_statement +from string import Template +import re, fnmatch, os, codecs, pickle + +class Module(object): + class Template(object): + def __init__(self, module): + self.module = module + + def _render_callback(self, cb): + if not cb: + return '{ NULL, NULL }' + return '{ "%s", &%s }' % (cb['short_name'], cb['symbol']) + + class DeclarationTemplate(Template): + def render(self): + out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + + if self.module.initialize: + out += "extern %s;\n" % self.module.initialize['declaration'] + + if self.module.cleanup: + out += "extern %s;\n" % self.module.cleanup['declaration'] + + return out + + class CallbacksTemplate(Template): + def render(self): + out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name + out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks) + out += "\n};\n" + return out + + class InfoTemplate(Template): + def render(self): + return Template( + r"""{ + "${clean_name}", + ${initialize}, + ${cleanup}, + ${cb_ptr}, ${cb_count}, ${enabled} + }""" + ).substitute( + clean_name = self.module.clean_name(), + initialize = self._render_callback(self.module.initialize), + cleanup = self._render_callback(self.module.cleanup), + cb_ptr = "_clar_cb_%s" % self.module.name, + cb_count = len(self.module.callbacks), + enabled = int(self.module.enabled) + ) + + def __init__(self, name): + self.name = name + + self.mtime = 0 + self.enabled = True + self.modified = False + + def clean_name(self): + return self.name.replace("_", "::") + + def _skip_comments(self, text): + SKIP_COMMENTS_REGEX = re.compile( + r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', + re.DOTALL | re.MULTILINE) + + def _replacer(match): + s = match.group(0) + return "" if s.startswith('/') else s + + return re.sub(SKIP_COMMENTS_REGEX, _replacer, text) + + def parse(self, contents): + TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{" + + contents = self._skip_comments(contents) + regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE) + + self.callbacks = [] + self.initialize = None + self.cleanup = None + + for (declaration, symbol, short_name) in regex.findall(contents): + data = { + "short_name" : short_name, + "declaration" : declaration, + "symbol" : symbol + } + + if short_name == 'initialize': + self.initialize = data + elif short_name == 'cleanup': + self.cleanup = data + else: + self.callbacks.append(data) + + return self.callbacks != [] + + def refresh(self, path): + self.modified = False + + try: + st = os.stat(path) + + # Not modified + if st.st_mtime == self.mtime: + return True + + self.modified = True + self.mtime = st.st_mtime + + with open(path) as fp: + raw_content = fp.read() + + except IOError: + return False + + return self.parse(raw_content) + +class TestSuite(object): + + def __init__(self, path): + self.path = path + + def should_generate(self, path): + if not os.path.isfile(path): + return True + + if any(module.modified for module in self.modules.values()): + return True + + return False + + def find_modules(self): + modules = [] + for root, _, files in os.walk(self.path): + module_root = root[len(self.path):] + module_root = [c for c in module_root.split(os.sep) if c] + + tests_in_module = fnmatch.filter(files, "*.c") + + for test_file in tests_in_module: + full_path = os.path.join(root, test_file) + module_name = "_".join(module_root + [test_file[:-2]]) + + modules.append((full_path, module_name)) + + return modules + + def load_cache(self): + path = os.path.join(self.path, '.clarcache') + cache = {} + + try: + fp = open(path) + cache = pickle.load(fp) + fp.close() + except IOError: + pass + + return cache + + def save_cache(self): + path = os.path.join(self.path, '.clarcache') + with open(path, 'w') as cache: + pickle.dump(self.modules, cache) + + def load(self, force = False): + module_data = self.find_modules() + self.modules = {} if force else self.load_cache() + + for path, name in module_data: + if name not in self.modules: + self.modules[name] = Module(name) + + if not self.modules[name].refresh(path): + del self.modules[name] + + def disable(self, excluded): + for exclude in excluded: + for module in self.modules.values(): + name = module.clean_name() + if name.startswith(exclude): + module.enabled = False + module.modified = True + + def suite_count(self): + return len(self.modules) + + def callback_count(self): + return sum(len(module.callbacks) for module in self.modules.values()) + + def write(self): + output = os.path.join(self.path, 'clar.suite') + + if not self.should_generate(output): + return False + + with open(output, 'w') as data: + for module in self.modules.values(): + t = Module.DeclarationTemplate(module) + data.write(t.render()) + + for module in self.modules.values(): + t = Module.CallbacksTemplate(module) + data.write(t.render()) + + suites = "static struct clar_suite _clar_suites[] = {" + ','.join( + Module.InfoTemplate(module).render() for module in self.modules.values() + ) + "};" + + data.write(suites) + + data.write("static const size_t _clar_suite_count = %d;" % self.suite_count()) + data.write("static const size_t _clar_callback_count = %d;" % self.callback_count()) + + suite.save_cache() + return True + +if __name__ == '__main__': + from optparse import OptionParser + + parser = OptionParser() + parser.add_option('-f', '--force', dest='force', default=False) + parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[]) + + options, args = parser.parse_args() + + for path in args or ['.']: + suite = TestSuite(path) + suite.load(options.force) + suite.disable(options.excluded) + if suite.write(): + print "Written `clar.suite` (%d suites)" % len(suite.modules) + From a218862557a877f2ebb77fc3fe4acca3feddfbd9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 02:35:23 +0100 Subject: [PATCH 16/37] Remove the submodule from travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2827fdbfb..8ce490356 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,6 @@ install: # Run the Build script script: - - git submodule update --init tests-clar/clar - mkdir _build - cd _build - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS From 4236164a77b57c42641530a523590a913ba299f9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 02:37:28 +0100 Subject: [PATCH 17/37] Prototypes warning goes away --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0862a082..742365281 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,7 +148,7 @@ IF (MSVC) # Precompiled headers ELSE () - SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes -Wmissing-prototypes ${CMAKE_C_FLAGS}") + SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra -Wno-missing-field-initializers -Wstrict-aliasing=2 -Wstrict-prototypes ${CMAKE_C_FLAGS}") IF (MINGW) # MinGW always does PIC and complains if we tell it to STRING(REGEX REPLACE "-fPIC" "" CMAKE_SHARED_LIBRARY_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}") ELSE () @@ -244,7 +244,6 @@ IF (BUILD_CLAR) INCLUDE_DIRECTORIES(${CLAR_PATH}) FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar.c") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-prototypes") ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite From 6fef1ab344326bbdeb45fd653e3c13c233600a35 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 3 Jan 2013 07:47:51 -0800 Subject: [PATCH 18/37] Tests should clean up after themselves --- tests-clar/core/env.c | 2 ++ tests-clar/index/tests.c | 1 + tests-clar/network/fetchlocal.c | 1 + tests-clar/odb/alternates.c | 5 +++++ tests-clar/status/worktree.c | 5 +++++ 5 files changed, 14 insertions(+) diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c index 9eb2fe5bb..d1d98885a 100644 --- a/tests-clar/core/env.c +++ b/tests-clar/core/env.c @@ -122,6 +122,8 @@ void test_core_env__0(void) } } #endif + + cl_fixture_cleanup(*val); } git_buf_free(&path); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 30a5a31fa..8359ce027 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -246,6 +246,7 @@ void test_index_tests__add(void) git_index_free(index); git_repository_free(repo); + cl_fixture_cleanup("myrepo"); } void test_index_tests__add_from_workdir_to_a_bare_repository_returns_EBAREPO(void) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 24949243e..48f30e7c5 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -33,6 +33,7 @@ void test_network_fetchlocal__complete(void) git_strarray_free(&refnames); git_remote_free(origin); git_repository_free(repo); + cl_fixture_cleanup("foo"); } void test_network_fetchlocal__partial(void) diff --git a/tests-clar/odb/alternates.c b/tests-clar/odb/alternates.c index 785d3bc84..c4b364b16 100644 --- a/tests-clar/odb/alternates.c +++ b/tests-clar/odb/alternates.c @@ -11,8 +11,13 @@ static git_repository *repo; void test_odb_alternates__cleanup(void) { + size_t i; + git_buf_free(&destpath); git_buf_free(&filepath); + + for (i=0; i Date: Thu, 3 Jan 2013 08:38:00 -0800 Subject: [PATCH 19/37] Cleanup after tests --- tests-clar/config/read.c | 1 + tests-clar/pack/packbuilder.c | 22 ++++++++++++++++++++++ tests-clar/stash/save.c | 1 + 3 files changed, 24 insertions(+) diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index e0171a593..d2ad0de58 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -441,6 +441,7 @@ void test_config_read__can_load_and_parse_an_empty_config_file(void) cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); git_config_free(cfg); + cl_fixture_cleanup("./empty"); } void test_config_read__cannot_load_a_non_existing_config_file(void) diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index b450be6b6..31823eac1 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "iterator.h" #include "vector.h" +#include "posix.h" static git_repository *_repo; static git_revwalk *_revwalker; @@ -72,6 +73,21 @@ static void seed_packbuilder(void) } } +static void cleanup_pack(const git_oid *oid) +{ + char *hash, path[1024] = {0}; + + hash = git_oid_allocfmt(oid); + + sprintf(path, "pack-%s.idx", hash); + p_unlink(path); + + sprintf(path, "pack-%s.pack", hash); + p_unlink(path); + + git__free(hash); +} + void test_pack_packbuilder__create_pack(void) { git_transfer_progress stats; @@ -82,6 +98,9 @@ void test_pack_packbuilder__create_pack(void) cl_git_pass(git_indexer_new(&_indexer, "testpack.pack")); cl_git_pass(git_indexer_run(_indexer, &stats)); cl_git_pass(git_indexer_write(_indexer)); + + cl_fixture_cleanup("testpack.pack"); + cleanup_pack(git_indexer_hash(_indexer)); } static git_transfer_progress stats; @@ -97,10 +116,13 @@ static int foreach_cb(void *buf, size_t len, void *payload) void test_pack_packbuilder__foreach(void) { git_indexer_stream *idx; + git_oid oid; seed_packbuilder(); cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + git_oid_cpy(&oid, git_indexer_stream_hash(idx)); git_indexer_stream_free(idx); + cleanup_pack(&oid); } diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index f8b427814..2302ebb4d 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -211,6 +211,7 @@ void test_stash_save__cannot_stash_against_a_bare_repository(void) git_stash_save(&stash_tip_oid, local, signature, NULL, GIT_STASH_DEFAULT)); git_repository_free(local); + cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party"); } void test_stash_save__can_stash_against_a_detached_head(void) From 600d8dbf6dccff5a9d86dd5ae01a53de46471796 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 3 Jan 2013 09:10:38 -0800 Subject: [PATCH 20/37] Move test cleanup into cleanup functions --- tests-clar/config/read.c | 6 +++- tests-clar/core/env.c | 32 ++++++++++++--------- tests-clar/index/tests.c | 6 +++- tests-clar/network/fetchlocal.c | 6 +++- tests-clar/pack/packbuilder.c | 49 +++++++++++++++++++-------------- tests-clar/stash/save.c | 2 +- tests-clar/status/worktree.c | 16 +++++++---- 7 files changed, 75 insertions(+), 42 deletions(-) diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index d2ad0de58..b603acb5c 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -1,5 +1,10 @@ #include "clar_libgit2.h" +void test_config_read__cleanup(void) +{ + cl_fixture_cleanup("./empty"); +} + void test_config_read__simple_read(void) { git_config *cfg; @@ -441,7 +446,6 @@ void test_config_read__can_load_and_parse_an_empty_config_file(void) cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); git_config_free(cfg); - cl_fixture_cleanup("./empty"); } void test_config_read__cannot_load_a_non_existing_config_file(void) diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c index d1d98885a..27e52ec3b 100644 --- a/tests-clar/core/env.c +++ b/tests-clar/core/env.c @@ -14,6 +14,18 @@ static const char *env_vars[NUM_VARS] = { "HOME" }; static char *env_save[NUM_VARS]; +static char *home_values[] = { + "fake_home", + "fáke_hõme", /* all in latin-1 supplement */ + "fĀke_Ĥome", /* latin extended */ + "fακε_hοmέ", /* having fun with greek */ + "faงe_นome", /* now I have no idea, but thai characters */ + "f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */ + "\xe1\xb8\x9fẢke_hoṁe", /* latin extended additional */ + "\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */ + NULL +}; + void test_core_env__initialize(void) { int i; @@ -24,6 +36,8 @@ void test_core_env__initialize(void) void test_core_env__cleanup(void) { int i; + char **val; + for (i = 0; i < NUM_VARS; ++i) { cl_setenv(env_vars[i], env_save[i]); #ifdef GIT_WIN32 @@ -31,11 +45,16 @@ void test_core_env__cleanup(void) #endif env_save[i] = NULL; } + + for (val = home_values; *val != NULL; val++) { + cl_fixture_cleanup(*val); + } } static void setenv_and_check(const char *name, const char *value) { char *check; + cl_git_pass(cl_setenv(name, value)); check = cl_getenv(name); cl_assert_equal_s(value, check); @@ -46,17 +65,6 @@ static void setenv_and_check(const char *name, const char *value) void test_core_env__0(void) { - static char *home_values[] = { - "fake_home", - "fáke_hõme", /* all in latin-1 supplement */ - "fĀke_Ĥome", /* latin extended */ - "fακε_hοmέ", /* having fun with greek */ - "faงe_นome", /* now I have no idea, but thai characters */ - "f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */ - "\xe1\xb8\x9fẢke_hoṁe", /* latin extended additional */ - "\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */ - NULL - }; git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT; char testfile[16], tidx = '0'; char **val; @@ -122,8 +130,6 @@ void test_core_env__0(void) } } #endif - - cl_fixture_cleanup(*val); } git_buf_free(&path); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 8359ce027..d2ad71cc6 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -24,6 +24,7 @@ static struct test_entry test_entries[] = { {48, "src/revobject.h", 1448, 0x4C3F7FE2} }; +static char *path_to_cleanup = NULL; // Helpers static void copy_file(const char *src, const char *dst) @@ -74,6 +75,9 @@ void test_index_tests__initialize(void) void test_index_tests__cleanup(void) { + if (path_to_cleanup) + cl_fixture_cleanup(path_to_cleanup); + path_to_cleanup = NULL; } @@ -246,7 +250,7 @@ void test_index_tests__add(void) git_index_free(index); git_repository_free(repo); - cl_fixture_cleanup("myrepo"); + path_to_cleanup = "myrepo"; } void test_index_tests__add_from_workdir_to_a_bare_repository_returns_EBAREPO(void) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 48f30e7c5..9ffbedbfe 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -11,6 +11,11 @@ static void transfer_cb(const git_transfer_progress *stats, void *payload) (*callcount)++; } +void test_network_fetchlocal__cleanup(void) +{ + cl_fixture_cleanup("foo"); +} + void test_network_fetchlocal__complete(void) { git_repository *repo; @@ -33,7 +38,6 @@ void test_network_fetchlocal__complete(void) git_strarray_free(&refnames); git_remote_free(origin); git_repository_free(repo); - cl_fixture_cleanup("foo"); } void test_network_fetchlocal__partial(void) diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index 31823eac1..c36b720e2 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -9,6 +9,26 @@ static git_packbuilder *_packbuilder; static git_indexer *_indexer; static git_vector _commits; static int _commits_is_initialized; +static char *path_to_cleanup = NULL; +static git_oid oid_to_cleanup = {{0}}; + +static void cleanup_pack(const git_oid *oid) +{ + char *hash, path[1024] = {0}; + + if (git_oid_iszero(&oid_to_cleanup)) return; + + hash = git_oid_allocfmt(oid); + + sprintf(path, "pack-%s.idx", hash); + p_unlink(path); + + sprintf(path, "pack-%s.pack", hash); + p_unlink(path); + + git__free(hash); + git_oid_fromstrn(&oid_to_cleanup, "", 0); +} void test_pack_packbuilder__initialize(void) { @@ -43,6 +63,12 @@ void test_pack_packbuilder__cleanup(void) git_repository_free(_repo); _repo = NULL; + + if (path_to_cleanup) + cl_fixture_cleanup(path_to_cleanup); + path_to_cleanup = NULL; + + cleanup_pack(&oid_to_cleanup); } static void seed_packbuilder(void) @@ -73,24 +99,10 @@ static void seed_packbuilder(void) } } -static void cleanup_pack(const git_oid *oid) -{ - char *hash, path[1024] = {0}; - - hash = git_oid_allocfmt(oid); - - sprintf(path, "pack-%s.idx", hash); - p_unlink(path); - - sprintf(path, "pack-%s.pack", hash); - p_unlink(path); - - git__free(hash); -} - void test_pack_packbuilder__create_pack(void) { git_transfer_progress stats; + path_to_cleanup = "testpack.pack"; seed_packbuilder(); cl_git_pass(git_packbuilder_write(_packbuilder, "testpack.pack")); @@ -98,9 +110,8 @@ void test_pack_packbuilder__create_pack(void) cl_git_pass(git_indexer_new(&_indexer, "testpack.pack")); cl_git_pass(git_indexer_run(_indexer, &stats)); cl_git_pass(git_indexer_write(_indexer)); + git_oid_cpy(&oid_to_cleanup, git_indexer_hash(_indexer)); - cl_fixture_cleanup("testpack.pack"); - cleanup_pack(git_indexer_hash(_indexer)); } static git_transfer_progress stats; @@ -116,13 +127,11 @@ static int foreach_cb(void *buf, size_t len, void *payload) void test_pack_packbuilder__foreach(void) { git_indexer_stream *idx; - git_oid oid; seed_packbuilder(); cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); cl_git_pass(git_indexer_stream_finalize(idx, &stats)); - git_oid_cpy(&oid, git_indexer_stream_hash(idx)); + git_oid_cpy(&oid_to_cleanup, git_indexer_stream_hash(idx)); git_indexer_stream_free(idx); - cleanup_pack(&oid); } diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index 2302ebb4d..e6033e1ef 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -32,6 +32,7 @@ void test_stash_save__cleanup(void) repo = NULL; cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party"); } static void assert_object_oid(const char* revision, const char* expected_oid, git_otype type) @@ -211,7 +212,6 @@ void test_stash_save__cannot_stash_against_a_bare_repository(void) git_stash_save(&stash_tip_oid, local, signature, NULL, GIT_STASH_DEFAULT)); git_repository_free(local); - cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party"); } void test_stash_save__can_stash_against_a_detached_head(void) diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 70fbca9e8..85363a970 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -6,6 +6,8 @@ #include "util.h" #include "path.h" +static char *path_to_cleanup = NULL; + /** * Initializer * @@ -25,6 +27,10 @@ void test_status_worktree__initialize(void) void test_status_worktree__cleanup(void) { cl_git_sandbox_cleanup(); + + if (path_to_cleanup) + cl_fixture_cleanup(path_to_cleanup); + path_to_cleanup = NULL; } /** @@ -446,7 +452,7 @@ void test_status_worktree__first_commit_in_progress(void) git_index_free(index); git_repository_free(repo); - cl_fixture_cleanup("getting_started"); + path_to_cleanup = "getting_started"; } @@ -596,7 +602,7 @@ void test_status_worktree__bracket_in_filename(void) git_index_free(index); git_repository_free(repo); - cl_fixture_cleanup("with_bracket"); + path_to_cleanup = "with_bracket"; } void test_status_worktree__space_in_filename(void) @@ -661,7 +667,7 @@ void test_status_worktree__space_in_filename(void) git_index_free(index); git_repository_free(repo); - cl_fixture_cleanup("with_space"); + path_to_cleanup = "with_space"; } static const char *filemode_paths[] = { @@ -772,7 +778,7 @@ void test_status_worktree__disable_pathspec_match(void) ); git_repository_free(repo); - cl_fixture_cleanup("pathspec"); + path_to_cleanup = "pathspec"; } @@ -825,7 +831,7 @@ void test_status_worktree__new_staged_file_must_handle_crlf(void) git_config_free(config); git_index_free(index); git_repository_free(repo); - cl_fixture_cleanup("getting_started"); + path_to_cleanup = "getting_started"; } void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void) From f6fded8f9110aa05fe3d947d9e53cbd5cc13d1d5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 19:07:41 +0100 Subject: [PATCH 21/37] Proper cleanup jeez --- tests-clar/config/read.c | 12 +++--- tests-clar/index/tests.c | 83 +++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index b603acb5c..9c02307ad 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -1,10 +1,5 @@ #include "clar_libgit2.h" -void test_config_read__cleanup(void) -{ - cl_fixture_cleanup("./empty"); -} - void test_config_read__simple_read(void) { git_config *cfg; @@ -436,11 +431,18 @@ void test_config_read__simple_read_from_specific_level(void) git_config_free(cfg); } +static void clean_empty_config(void *unused) +{ + GIT_UNUSED(unused); + cl_fixture_cleanup("./empty"); +} + void test_config_read__can_load_and_parse_an_empty_config_file(void) { git_config *cfg; int i; + cl_set_cleanup(&clean_empty_config, NULL); cl_git_mkfile("./empty", ""); cl_git_pass(git_config_open_ondisk(&cfg, "./empty")); cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index d2ad71cc6..989734c1b 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -24,8 +24,6 @@ static struct test_entry test_entries[] = { {48, "src/revobject.h", 1448, 0x4C3F7FE2} }; -static char *path_to_cleanup = NULL; - // Helpers static void copy_file(const char *src, const char *dst) { @@ -73,14 +71,6 @@ void test_index_tests__initialize(void) { } -void test_index_tests__cleanup(void) -{ - if (path_to_cleanup) - cl_fixture_cleanup(path_to_cleanup); - path_to_cleanup = NULL; -} - - void test_index_tests__empty_index(void) { git_index *index; @@ -207,50 +197,57 @@ void test_index_tests__sort1(void) git_index_free(index); } +static void cleanup_myrepo(void *opaque) +{ + GIT_UNUSED(opaque); + cl_fixture_cleanup("myrepo"); +} + void test_index_tests__add(void) { - git_index *index; - git_filebuf file = GIT_FILEBUF_INIT; - git_repository *repo; - const git_index_entry *entry; - git_oid id1; + git_index *index; + git_filebuf file = GIT_FILEBUF_INIT; + git_repository *repo; + const git_index_entry *entry; + git_oid id1; - /* Intialize a new repository */ - cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_set_cleanup(&cleanup_myrepo, NULL); - /* Ensure we're the only guy in the room */ - cl_git_pass(git_repository_index(&index, repo)); - cl_assert(git_index_entrycount(index) == 0); + /* Intialize a new repository */ + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); - /* Create a new file in the working directory */ - cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); - cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0)); - cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); - cl_git_pass(git_filebuf_commit(&file, 0666)); + /* Ensure we're the only guy in the room */ + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(git_index_entrycount(index) == 0); - /* Store the expected hash of the file/blob - * This has been generated by executing the following - * $ echo "hey there" | git hash-object --stdin - */ - cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + /* Create a new file in the working directory */ + cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); + cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0)); + cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); + cl_git_pass(git_filebuf_commit(&file, 0666)); - /* Add the new file to the index */ - cl_git_pass(git_index_add_from_workdir(index, "test.txt")); + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ echo "hey there" | git hash-object --stdin + */ + cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); - /* Wow... it worked! */ - cl_assert(git_index_entrycount(index) == 1); - entry = git_index_get_byindex(index, 0); + /* Add the new file to the index */ + cl_git_pass(git_index_add_from_workdir(index, "test.txt")); - /* And the built-in hashing mechanism worked as expected */ - cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + /* Wow... it worked! */ + cl_assert(git_index_entrycount(index) == 1); + entry = git_index_get_byindex(index, 0); - /* Test access by path instead of index */ - cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); - cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + /* And the built-in hashing mechanism worked as expected */ + cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); - git_index_free(index); - git_repository_free(repo); - path_to_cleanup = "myrepo"; + /* Test access by path instead of index */ + cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + + git_index_free(index); + git_repository_free(repo); } void test_index_tests__add_from_workdir_to_a_bare_repository_returns_EBAREPO(void) From 7b51d675e89371661a6c97f76050d4b2477e171a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jan 2013 19:17:07 +0100 Subject: [PATCH 22/37] Even more cleanups --- tests-clar/network/fetchlocal.c | 15 ++++++++++---- tests-clar/odb/alternates.c | 4 ++-- tests-clar/pack/packbuilder.c | 36 ++------------------------------- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 9ffbedbfe..ee3bd9db3 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -11,9 +11,9 @@ static void transfer_cb(const git_transfer_progress *stats, void *payload) (*callcount)++; } -void test_network_fetchlocal__cleanup(void) +static void cleanup_local_repo(void *path) { - cl_fixture_cleanup("foo"); + cl_fixture_cleanup((char *)path); } void test_network_fetchlocal__complete(void) @@ -24,6 +24,8 @@ void test_network_fetchlocal__complete(void) git_strarray refnames = {0}; const char *url = cl_git_fixture_url("testrepo.git"); + + cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); @@ -40,6 +42,12 @@ void test_network_fetchlocal__complete(void) git_repository_free(repo); } +static void cleanup_sandbox(void *unused) +{ + GIT_UNUSED(unused); + cl_git_sandbox_cleanup(); +} + void test_network_fetchlocal__partial(void) { git_repository *repo = cl_git_sandbox_init("partial-testrepo"); @@ -48,6 +56,7 @@ void test_network_fetchlocal__partial(void) git_strarray refnames = {0}; const char *url; + cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL)); cl_assert_equal_i(1, (int)refnames.count); @@ -65,6 +74,4 @@ void test_network_fetchlocal__partial(void) git_strarray_free(&refnames); git_remote_free(origin); - - cl_git_sandbox_cleanup(); } diff --git a/tests-clar/odb/alternates.c b/tests-clar/odb/alternates.c index c4b364b16..be7bfa9cd 100644 --- a/tests-clar/odb/alternates.c +++ b/tests-clar/odb/alternates.c @@ -6,7 +6,7 @@ static git_buf destpath, filepath; static const char *paths[] = { "A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git" }; -static git_filebuf file; +static git_filebuf file; static git_repository *repo; void test_odb_alternates__cleanup(void) @@ -16,7 +16,7 @@ void test_odb_alternates__cleanup(void) git_buf_free(&destpath); git_buf_free(&filepath); - for (i=0; i Date: Thu, 3 Jan 2013 19:38:29 +0100 Subject: [PATCH 23/37] Status tests... --- tests-clar/status/worktree.c | 402 +++--------------------------- tests-clar/status/worktree_init.c | 342 +++++++++++++++++++++++++ 2 files changed, 370 insertions(+), 374 deletions(-) create mode 100644 tests-clar/status/worktree_init.c diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 85363a970..6786b91ff 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -6,18 +6,6 @@ #include "util.h" #include "path.h" -static char *path_to_cleanup = NULL; - -/** - * Initializer - * - * Not all of the tests in this file use the same fixtures, so we allow each - * test to load their fixture at the top of the test function. - */ -void test_status_worktree__initialize(void) -{ -} - /** * Cleanup * @@ -27,10 +15,6 @@ void test_status_worktree__initialize(void) void test_status_worktree__cleanup(void) { cl_git_sandbox_cleanup(); - - if (path_to_cleanup) - cl_fixture_cleanup(path_to_cleanup); - path_to_cleanup = NULL; } /** @@ -415,259 +399,43 @@ void test_status_worktree__issue_592_ignored_dirs_with_tracked_content(void) */ } -void test_status_worktree__cannot_retrieve_the_status_of_a_bare_repository(void) +void test_status_worktree__conflict_with_diff3(void) { - git_repository *repo; - unsigned int status = 0; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - cl_assert_equal_i(GIT_EBAREREPO, git_status_file(&status, repo, "dummy")); - - git_repository_free(repo); -} - -void test_status_worktree__first_commit_in_progress(void) -{ - git_repository *repo; + git_repository *repo = cl_git_sandbox_init("status"); git_index *index; - status_entry_single result; + unsigned int status; + git_index_entry ancestor_entry, our_entry, their_entry; - cl_git_pass(git_repository_init(&repo, "getting_started", 0)); - cl_git_mkfile("getting_started/testfile.txt", "content\n"); + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); + ancestor_entry.path = "modified_file"; + git_oid_fromstr(&ancestor_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + our_entry.path = "modified_file"; + git_oid_fromstr(&our_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + their_entry.path = "modified_file"; + git_oid_fromstr(&their_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); - cl_git_pass(git_index_write(index)); - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); + cl_git_pass(git_index_remove(index, "modified_file", 0)); + cl_git_pass(git_index_conflict_add(index, &ancestor_entry, + &our_entry, &their_entry)); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + + cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); git_index_free(index); - git_repository_free(repo); - path_to_cleanup = "getting_started"; -} - - - -void test_status_worktree__status_file_without_index_or_workdir(void) -{ - git_repository *repo; - unsigned int status = 0; - git_index *index; - - cl_git_pass(p_mkdir("wd", 0777)); - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_set_workdir(repo, "wd", false)); - - cl_git_pass(git_index_open(&index, "empty-index")); - cl_assert_equal_i(0, (int)git_index_entrycount(index)); - git_repository_set_index(repo, index); - - cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); - - cl_assert_equal_i(GIT_STATUS_INDEX_DELETED, status); - - git_repository_free(repo); - git_index_free(index); - cl_git_pass(p_rmdir("wd")); -} - -static void fill_index_wth_head_entries(git_repository *repo, git_index *index) -{ - git_oid oid; - git_commit *commit; - git_tree *tree; - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_commit_tree(&tree, commit)); - - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_write(index)); - - git_tree_free(tree); - git_commit_free(commit); -} - -void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void) -{ - git_repository *repo; - unsigned int status = 0; - git_index *index; - - cl_git_pass(p_mkdir("wd", 0777)); - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_set_workdir(repo, "wd", false)); - - cl_git_pass(git_index_open(&index, "my-index")); - fill_index_wth_head_entries(repo, index); - - git_repository_set_index(repo, index); - - cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); - - cl_assert_equal_i(GIT_STATUS_WT_DELETED, status); - - git_repository_free(repo); - git_index_free(index); - cl_git_pass(p_rmdir("wd")); - cl_git_pass(p_unlink("my-index")); -} - -void test_status_worktree__bracket_in_filename(void) -{ - git_repository *repo; - git_index *index; - status_entry_single result; - unsigned int status_flags; - int error; - - #define FILE_WITH_BRACKET "LICENSE[1].md" - #define FILE_WITHOUT_BRACKET "LICENSE1.md" - - cl_git_pass(git_repository_init(&repo, "with_bracket", 0)); - cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET, "I have a bracket in my name\n"); - - /* file is new to working directory */ - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* ignore the file */ - - cl_git_rewritefile("with_bracket/.gitignore", "*.md\n.gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_IGNORED); - - /* don't ignore the file */ - - cl_git_rewritefile("with_bracket/.gitignore", ".gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* add the file to the index */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_BRACKET)); - cl_git_pass(git_index_write(index)); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - /* Create file without bracket */ - - cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET, "I have no bracket in my name!\n"); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITHOUT_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, "LICENSE\\[1\\].md")); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - error = git_status_file(&status_flags, repo, FILE_WITH_BRACKET); - cl_git_fail(error); - cl_assert_equal_i(GIT_EAMBIGUOUS, error); - - git_index_free(index); - git_repository_free(repo); - path_to_cleanup = "with_bracket"; -} - -void test_status_worktree__space_in_filename(void) -{ - git_repository *repo; - git_index *index; - status_entry_single result; - unsigned int status_flags; - -#define FILE_WITH_SPACE "LICENSE - copy.md" - - cl_git_pass(git_repository_init(&repo, "with_space", 0)); - cl_git_mkfile("with_space/" FILE_WITH_SPACE, "I have a space in my name\n"); - - /* file is new to working directory */ - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* ignore the file */ - - cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_IGNORED); - - /* don't ignore the file */ - - cl_git_rewritefile("with_space/.gitignore", ".gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* add the file to the index */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_SPACE)); - cl_git_pass(git_index_write(index)); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - git_index_free(index); - git_repository_free(repo); - path_to_cleanup = "with_space"; } static const char *filemode_paths[] = { @@ -735,53 +503,6 @@ void test_status_worktree__filemode_changes(void) git_config_free(cfg); } -static int cb_status__expected_path(const char *p, unsigned int s, void *payload) -{ - const char *expected_path = (const char *)payload; - - GIT_UNUSED(s); - - if (payload == NULL) - cl_fail("Unexpected path"); - - cl_assert_equal_s(expected_path, p); - - return 0; -} - -void test_status_worktree__disable_pathspec_match(void) -{ - git_repository *repo; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - char *file_with_bracket = "LICENSE[1].md", - *imaginary_file_with_bracket = "LICENSE[1-2].md"; - - cl_git_pass(git_repository_init(&repo, "pathspec", 0)); - cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n"); - cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n"); - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; - opts.pathspec.count = 1; - opts.pathspec.strings = &file_with_bracket; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__expected_path, - file_with_bracket) - ); - - /* Test passing a pathspec matching files in the workdir. */ - /* Must not match because pathspecs are disabled. */ - opts.pathspec.strings = &imaginary_file_with_bracket; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__expected_path, NULL) - ); - - git_repository_free(repo); - path_to_cleanup = "pathspec"; -} - - static int cb_status__interrupt(const char *p, unsigned int s, void *payload) { volatile int *count = (int *)payload; @@ -806,34 +527,6 @@ void test_status_worktree__interruptable_foreach(void) cl_assert_equal_i(8, count); } -void test_status_worktree__new_staged_file_must_handle_crlf(void) -{ - git_repository *repo; - git_index *index; - git_config *config; - unsigned int status; - - cl_git_pass(git_repository_init(&repo, "getting_started", 0)); - - // Ensure that repo has core.autocrlf=true - cl_git_pass(git_repository_config(&config, repo)); - cl_git_pass(git_config_set_bool(config, "core.autocrlf", true)); - - cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); // Content with CRLF - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_file(&status, repo, "testfile.txt")); - cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status); - - git_config_free(config); - git_index_free(index); - git_repository_free(repo); - path_to_cleanup = "getting_started"; -} - void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void) { git_repository *repo = cl_git_sandbox_init("status"); @@ -887,42 +580,3 @@ void test_status_worktree__conflicted_item(void) git_index_free(index); } -void test_status_worktree__conflict_with_diff3(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_index *index; - unsigned int status; - git_index_entry ancestor_entry, our_entry, their_entry; - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "modified_file"; - git_oid_fromstr(&ancestor_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - our_entry.path = "modified_file"; - git_oid_fromstr(&our_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - their_entry.path = "modified_file"; - git_oid_fromstr(&their_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); - - cl_git_pass(git_repository_index(&index, repo)); - - cl_git_pass(git_index_remove(index, "modified_file", 0)); - cl_git_pass(git_index_conflict_add(index, &ancestor_entry, - &our_entry, &their_entry)); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - - cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); - - git_index_free(index); -} - diff --git a/tests-clar/status/worktree_init.c b/tests-clar/status/worktree_init.c new file mode 100644 index 000000000..6d790b1c9 --- /dev/null +++ b/tests-clar/status/worktree_init.c @@ -0,0 +1,342 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "ignore.h" +#include "status_helpers.h" +#include "posix.h" +#include "util.h" +#include "path.h" + +static void cleanup_new_repo(void *path) +{ + cl_fixture_cleanup((char *)path); +} + +void test_status_worktree_init__cannot_retrieve_the_status_of_a_bare_repository(void) +{ + git_repository *repo; + unsigned int status = 0; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_assert_equal_i(GIT_EBAREREPO, git_status_file(&status, repo, "dummy")); + git_repository_free(repo); +} + +void test_status_worktree_init__first_commit_in_progress(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + + cl_set_cleanup(&cleanup_new_repo, "getting_started"); + + cl_git_pass(git_repository_init(&repo, "getting_started", 0)); + cl_git_mkfile("getting_started/testfile.txt", "content\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + git_index_free(index); + git_repository_free(repo); +} + + + +void test_status_worktree_init__status_file_without_index_or_workdir(void) +{ + git_repository *repo; + unsigned int status = 0; + git_index *index; + + cl_git_pass(p_mkdir("wd", 0777)); + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_set_workdir(repo, "wd", false)); + + cl_git_pass(git_index_open(&index, "empty-index")); + cl_assert_equal_i(0, (int)git_index_entrycount(index)); + git_repository_set_index(repo, index); + + cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); + + cl_assert_equal_i(GIT_STATUS_INDEX_DELETED, status); + + git_repository_free(repo); + git_index_free(index); + cl_git_pass(p_rmdir("wd")); +} + +static void fill_index_wth_head_entries(git_repository *repo, git_index *index) +{ + git_oid oid; + git_commit *commit; + git_tree *tree; + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + cl_git_pass(git_commit_tree(&tree, commit)); + + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_write(index)); + + git_tree_free(tree); + git_commit_free(commit); +} + +void test_status_worktree_init__status_file_with_clean_index_and_empty_workdir(void) +{ + git_repository *repo; + unsigned int status = 0; + git_index *index; + + cl_git_pass(p_mkdir("wd", 0777)); + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_set_workdir(repo, "wd", false)); + + cl_git_pass(git_index_open(&index, "my-index")); + fill_index_wth_head_entries(repo, index); + + git_repository_set_index(repo, index); + + cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); + + cl_assert_equal_i(GIT_STATUS_WT_DELETED, status); + + git_repository_free(repo); + git_index_free(index); + cl_git_pass(p_rmdir("wd")); + cl_git_pass(p_unlink("my-index")); +} + +void test_status_worktree_init__bracket_in_filename(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + unsigned int status_flags; + int error; + + #define FILE_WITH_BRACKET "LICENSE[1].md" + #define FILE_WITHOUT_BRACKET "LICENSE1.md" + + cl_set_cleanup(&cleanup_new_repo, "with_bracket"); + + cl_git_pass(git_repository_init(&repo, "with_bracket", 0)); + cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET, "I have a bracket in my name\n"); + + /* file is new to working directory */ + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* ignore the file */ + + cl_git_rewritefile("with_bracket/.gitignore", "*.md\n.gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_IGNORED); + + /* don't ignore the file */ + + cl_git_rewritefile("with_bracket/.gitignore", ".gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* add the file to the index */ + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_BRACKET)); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + /* Create file without bracket */ + + cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET, "I have no bracket in my name!\n"); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITHOUT_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, "LICENSE\\[1\\].md")); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + error = git_status_file(&status_flags, repo, FILE_WITH_BRACKET); + cl_git_fail(error); + cl_assert_equal_i(GIT_EAMBIGUOUS, error); + + git_index_free(index); + git_repository_free(repo); +} + +void test_status_worktree_init__space_in_filename(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + unsigned int status_flags; + +#define FILE_WITH_SPACE "LICENSE - copy.md" + + cl_set_cleanup(&cleanup_new_repo, "with_space"); + cl_git_pass(git_repository_init(&repo, "with_space", 0)); + cl_git_mkfile("with_space/" FILE_WITH_SPACE, "I have a space in my name\n"); + + /* file is new to working directory */ + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* ignore the file */ + + cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_IGNORED); + + /* don't ignore the file */ + + cl_git_rewritefile("with_space/.gitignore", ".gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* add the file to the index */ + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_from_workdir(index, FILE_WITH_SPACE)); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + git_index_free(index); + git_repository_free(repo); +} + +static int cb_status__expected_path(const char *p, unsigned int s, void *payload) +{ + const char *expected_path = (const char *)payload; + + GIT_UNUSED(s); + + if (payload == NULL) + cl_fail("Unexpected path"); + + cl_assert_equal_s(expected_path, p); + + return 0; +} + +void test_status_worktree_init__disable_pathspec_match(void) +{ + git_repository *repo; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + char *file_with_bracket = "LICENSE[1].md", + *imaginary_file_with_bracket = "LICENSE[1-2].md"; + + cl_set_cleanup(&cleanup_new_repo, "pathspec"); + cl_git_pass(git_repository_init(&repo, "pathspec", 0)); + cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n"); + cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n"); + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; + opts.pathspec.count = 1; + opts.pathspec.strings = &file_with_bracket; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__expected_path, + file_with_bracket) + ); + + /* Test passing a pathspec matching files in the workdir. */ + /* Must not match because pathspecs are disabled. */ + opts.pathspec.strings = &imaginary_file_with_bracket; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__expected_path, NULL) + ); + + git_repository_free(repo); +} + +void test_status_worktree_init__new_staged_file_must_handle_crlf(void) +{ + git_repository *repo; + git_index *index; + git_config *config; + unsigned int status; + + cl_set_cleanup(&cleanup_new_repo, "getting_started"); + cl_git_pass(git_repository_init(&repo, "getting_started", 0)); + + // Ensure that repo has core.autocrlf=true + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_bool(config, "core.autocrlf", true)); + + cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); // Content with CRLF + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_from_workdir(index, "testfile.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_file(&status, repo, "testfile.txt")); + cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status); + + git_config_free(config); + git_index_free(index); + git_repository_free(repo); +} + From b8a1ea7cf9e23e394d09b0d051b696bd7acc2cf9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 3 Jan 2013 11:04:03 -0800 Subject: [PATCH 24/37] Fix core::env cleanup code Mark fake home directories that failed to be created, so we won't try to remove them and have cleanup just use p_rmdir. --- tests-clar/core/env.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c index 27e52ec3b..72ef66819 100644 --- a/tests-clar/core/env.c +++ b/tests-clar/core/env.c @@ -46,8 +46,12 @@ void test_core_env__cleanup(void) env_save[i] = NULL; } + /* these will probably have already been cleaned up, but if a test + * fails, then it's probably good to try and clear out these dirs + */ for (val = home_values; *val != NULL; val++) { - cl_fixture_cleanup(*val); + if (**val != '\0') + (void)p_rmdir(*val); } } @@ -79,8 +83,10 @@ void test_core_env__0(void) * we are on a filesystem that doesn't support the * characters in question and skip this test... */ - if (p_mkdir(*val, 0777) != 0) + if (p_mkdir(*val, 0777) != 0) { + *val = ""; /* mark as not created */ continue; + } cl_git_pass(git_path_prettify(&path, *val, NULL)); @@ -130,6 +136,8 @@ void test_core_env__0(void) } } #endif + + (void)p_rmdir(*val); } git_buf_free(&path); From b421decc76a60cd964d58ced87b9012370045dab Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Thu, 3 Jan 2013 15:43:51 +0200 Subject: [PATCH 25/37] notes.c - whitespace fix --- src/notes.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/notes.c b/src/notes.c index 8a27bdbf5..b49a1b524 100644 --- a/src/notes.c +++ b/src/notes.c @@ -129,10 +129,10 @@ static int manipulate_note_in_tree_r( git_tree *parent, git_oid *note_oid, const char *annotated_object_sha, - int fanout, + int fanout, int (*note_exists_cb)( - git_tree **out, - git_repository *repo, + git_tree **out, + git_repository *repo, git_tree *parent, git_oid *note_oid, const char *annotated_object_sha, @@ -147,7 +147,7 @@ static int manipulate_note_in_tree_r( int fanout, int current_error)) { - int error = -1; + int error = -1; git_tree *subtree = NULL, *new = NULL; char subtree_name[3]; @@ -275,7 +275,7 @@ static int note_write(git_oid *out, int error; git_oid oid; git_tree *tree = NULL; - + // TODO: should we apply filters? /* create note object */ if ((error = git_blob_create_frombuffer(&oid, repo, note, strlen(note))) < 0) @@ -351,7 +351,7 @@ static int note_remove(git_repository *repo, int error; git_tree *tree_after_removal = NULL; git_oid oid; - + if ((error = manipulate_note_in_tree_r( &tree_after_removal, repo, tree, NULL, target, 0, remove_note_in_tree_eexists_cb, remove_note_in_tree_enotfound_cb)) < 0) From 853488eed45f2f620fdfc4879827df02bc11553e Mon Sep 17 00:00:00 2001 From: Philip Kelley Date: Thu, 3 Jan 2013 08:45:09 -0500 Subject: [PATCH 26/37] Fix git__strncasecmp --- src/util.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/util.c b/src/util.c index 059e55dd7..ba849aa1a 100644 --- a/src/util.c +++ b/src/util.c @@ -199,17 +199,15 @@ int git__strncmp(const char *a, const char *b, size_t sz) int git__strncasecmp(const char *a, const char *b, size_t sz) { - int al = 0, bl = 0; + int al, bl; - while (sz && *a && *b) { + do { al = (unsigned char)tolower(*a); bl = (unsigned char)tolower(*b); - if (al != bl) - break; - --sz, ++a, ++b; - } + ++a, ++b; + } while (--sz && al && al == bl); - return !sz ? 0 : al - bl; + return al - bl; } void git__strntolower(char *str, size_t len) From b60b4562feac6c17dde9159c437e6e5a908d628e Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Thu, 3 Jan 2013 16:31:36 +0200 Subject: [PATCH 27/37] add option to allow git note overwrite --- include/git2/notes.h | 4 +++- src/notes.c | 11 +++++++---- tests-clar/notes/notes.c | 32 ++++++++++++++++++++++++++++---- tests-clar/notes/notesref.c | 2 +- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/git2/notes.h b/include/git2/notes.h index ae66975cd..ddd54b039 100644 --- a/include/git2/notes.h +++ b/include/git2/notes.h @@ -76,6 +76,7 @@ GIT_EXTERN(const git_oid *) git_note_oid(const git_note *note); * defaults to "refs/notes/commits" * @param oid OID of the git object to decorate * @param note Content of the note to add for object oid + * @param force Overwrite existing note * * @return 0 or an error code */ @@ -86,7 +87,8 @@ GIT_EXTERN(int) git_note_create( const git_signature *committer, const char *notes_ref, const git_oid *oid, - const char *note); + const char *note, + int force); /** diff --git a/src/notes.c b/src/notes.c index b49a1b524..c0ff48f7d 100644 --- a/src/notes.c +++ b/src/notes.c @@ -270,7 +270,8 @@ static int note_write(git_oid *out, const char *note, git_tree *commit_tree, const char *target, - git_commit **parents) + git_commit **parents, + int allow_note_overwrite) { int error; git_oid oid; @@ -283,7 +284,8 @@ static int note_write(git_oid *out, if ((error = manipulate_note_in_tree_r( &tree, repo, commit_tree, &oid, target, 0, - insert_note_in_tree_eexists_cb, insert_note_in_tree_enotfound_cb)) < 0) + allow_note_overwrite ? insert_note_in_tree_enotfound_cb : insert_note_in_tree_eexists_cb, + insert_note_in_tree_enotfound_cb)) < 0) goto cleanup; if (out) @@ -449,7 +451,8 @@ int git_note_create( const git_signature *committer, const char *notes_ref, const git_oid *oid, - const char *note) + const char *note, + int allow_note_overwrite) { int error; char *target = NULL; @@ -465,7 +468,7 @@ int git_note_create( goto cleanup; error = note_write(out, repo, author, committer, notes_ref, - note, tree, target, &commit); + note, tree, target, &commit, allow_note_overwrite); cleanup: git__free(target); diff --git a/tests-clar/notes/notes.c b/tests-clar/notes/notes.c index 3f5194c51..ee0b6c2f8 100644 --- a/tests-clar/notes/notes.c +++ b/tests-clar/notes/notes.c @@ -34,7 +34,7 @@ static void create_note(git_oid *note_oid, const char *canonical_namespace, cons git_oid oid; cl_git_pass(git_oid_fromstr(&oid, target_sha)); - cl_git_pass(git_note_create(note_oid, _repo, _sig, _sig, canonical_namespace, &oid, message)); + cl_git_pass(git_note_create(note_oid, _repo, _sig, _sig, canonical_namespace, &oid, message, 0)); } static struct { @@ -194,16 +194,40 @@ void test_notes_notes__creating_a_note_on_a_target_which_already_has_one_returns cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); - error = git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello world\n"); + error = git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello world\n", 0); cl_git_fail(error); cl_assert_equal_i(GIT_EEXISTS, error); create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); - error = git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello world\n"); + error = git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello world\n", 0); cl_git_fail(error); cl_assert_equal_i(GIT_EEXISTS, error); } + +void test_notes_notes__creating_a_note_on_a_target_can_overwrite_existing_note(void) +{ + git_oid note_oid, target_oid; + git_note *note, *namespace_note; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + + create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello new world\n", 1)); + + cl_git_pass(git_note_read(¬e, _repo, NULL, &target_oid)); + assert_note_equal(note, "hello new world\n", ¬e_oid); + + create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello new ref world\n", 1)); + + cl_git_pass(git_note_read(&namespace_note, _repo, "refs/notes/some/namespace", &target_oid)); + assert_note_equal(namespace_note, "hello new ref world\n", ¬e_oid); + + git_note_free(note); + git_note_free(namespace_note); +} + static char *messages[] = { "08c041783f40edfe12bb406c9c9a8a040177c125", "96c45fbe09ab7445fc7c60fd8d17f32494399343", @@ -244,7 +268,7 @@ void test_notes_notes__can_insert_a_note_in_an_existing_fanout(void) cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); for (i = 0; i < MESSAGES_COUNT; i++) { - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/fanout", &target_oid, messages[i])); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/fanout", &target_oid, messages[i], 0)); cl_git_pass(git_note_read(&_note, _repo, "refs/notes/fanout", &target_oid)); git_note_free(_note); diff --git a/tests-clar/notes/notesref.c b/tests-clar/notes/notesref.c index d26056f4b..633628c69 100644 --- a/tests-clar/notes/notesref.c +++ b/tests-clar/notes/notesref.c @@ -42,7 +42,7 @@ void test_notes_notesref__config_corenotesref(void) cl_git_pass(git_config_set_string(_cfg, "core.notesRef", "refs/notes/mydefaultnotesref")); - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &oid, "test123test\n")); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &oid, "test123test\n", 0)); cl_git_pass(git_note_read(&_note, _repo, NULL, &oid)); cl_assert(!strcmp(git_note_message(_note), "test123test\n")); From 35560d6d14fbdce1be2b87680b4af55fe6c15c09 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 3 Jan 2013 15:53:50 -0600 Subject: [PATCH 28/37] expose merge metadata cleanup --- include/git2/repository.h | 9 +++++++++ src/merge.c | 2 +- src/merge.h | 1 - src/reset.c | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 96b47f440..02e689111 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -490,6 +490,15 @@ GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *re */ GIT_EXTERN(int) git_repository_message_remove(git_repository *repo); +/** + * Remove all the metadata associated with an ongoing git merge, including + * MERGE_HEAD, MERGE_MSG, etc. + * + * @param repo A repository object + * @return 0 on success, or error + */ +GIT_EXTERN(int) git_repository_merge_cleanup(git_repository *repo); + typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name, const char *remote_url, const git_oid *oid, diff --git a/src/merge.c b/src/merge.c index 1386d0908..dfdadca81 100644 --- a/src/merge.c +++ b/src/merge.c @@ -15,7 +15,7 @@ #include "git2/reset.h" #include "commit_list.h" -int git_merge__cleanup(git_repository *repo) +int git_repository_merge_cleanup(git_repository *repo) { int error = 0; git_buf merge_head_path = GIT_BUF_INIT, diff --git a/src/merge.h b/src/merge.h index 3681e24b7..af24de474 100644 --- a/src/merge.h +++ b/src/merge.h @@ -16,7 +16,6 @@ #define MERGE_CONFIG_FILE_MODE 0666 -int git_merge__cleanup(git_repository *repo); int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos); #endif diff --git a/src/reset.c b/src/reset.c index 17b4b900c..784094a1f 100644 --- a/src/reset.c +++ b/src/reset.c @@ -126,7 +126,7 @@ int git_reset( goto cleanup; } - if ((error = git_merge__cleanup(repo)) < 0) { + if ((error = git_repository_merge_cleanup(repo)) < 0) { giterr_set(GITERR_INDEX, "%s - Failed to clean up merge data.", ERROR_MSG); goto cleanup; } From 931b8b709c0d2e1f42f258f61e88e457db9e4275 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Thu, 3 Jan 2013 22:16:37 +0000 Subject: [PATCH 29/37] Add Apache license header back to libpqueue files The original libpqueue file were licensed under Apache 2.0 so therefore should retain their copyrights and header as per the license terms at http://www.apache.org/licenses/LICENSE-2.0 --- src/pqueue.c | 22 ++++++++++++++++++++++ src/pqueue.h | 24 +++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/pqueue.c b/src/pqueue.c index cb59c13ec..34e3db0eb 100644 --- a/src/pqueue.c +++ b/src/pqueue.c @@ -3,6 +3,28 @@ * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. + * + * This file is based on a modified version of the priority queue found + * in the Apache project and libpqueue library. + * + * https://github.com/vy/libpqueue + * + * Original file notice: + * + * Copyright 2010 Volkan Yazici + * Copyright 2006-2010 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. */ #include "common.h" diff --git a/src/pqueue.h b/src/pqueue.h index a3e1edd1d..0648141bb 100644 --- a/src/pqueue.h +++ b/src/pqueue.h @@ -1,8 +1,30 @@ /* - * Copyright (C) 2009-2012 the libgit2 contributors + * Copyright (C) 2009-2013 the libgit2 contributors * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. + * + * This file is based on a modified version of the priority queue found + * in the Apache project and libpqueue library. + * + * https://github.com/vy/libpqueue + * + * Original file notice: + * + * Copyright 2010 Volkan Yazici + * Copyright 2006-2010 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. */ #ifndef INCLUDE_pqueue_h__ From d73d52dfcb589b1bc09a5ed7c4f39b0ddc21e2a9 Mon Sep 17 00:00:00 2001 From: Congyi Wu Date: Thu, 3 Jan 2013 13:26:11 -0500 Subject: [PATCH 30/37] Fix bug in gen_pktline() for deletes of missing remote refs * gen_pktline() in smart_protocol.c was skipping refspecs that deleted refs that were not advertised by the server. The new behavior is to send a delete command with an old-id of zero, which matches the behavior of the official git client. * Update test_network_push__delete() in reaction to above fix. * Obviate messy logic that handles missing push_spec rrefs by canonicalizing push_spec. After calculate_work(), loid, roid, and rref, are filled in with exactly what is sent to the server --- src/push.c | 53 +++++++++++-------------------- src/transports/smart_protocol.c | 55 ++++++--------------------------- tests-clar/online/push.c | 16 ++++++---- 3 files changed, 38 insertions(+), 86 deletions(-) diff --git a/src/push.c b/src/push.c index 1d63d574e..efca743b3 100644 --- a/src/push.c +++ b/src/push.c @@ -101,24 +101,27 @@ static int parse_refspec(push_spec **spec, const char *str) if (delim == NULL) { s->lref = git__strdup(str); check(s->lref); - s->rref = NULL; } else { if (delim - str) { s->lref = git__strndup(str, delim - str); check(s->lref); - } else - s->lref = NULL; + } if (strlen(delim + 1)) { s->rref = git__strdup(delim + 1); check(s->rref); - } else - s->rref = NULL; + } } if (!s->lref && !s->rref) goto on_error; + /* If rref is ommitted, use the same ref name as lref */ + if (!s->rref) { + s->rref = git__strdup(s->lref); + check(s->rref); + } + #undef check *spec = s; @@ -282,44 +285,24 @@ static int calculate_work(git_push *push) push_spec *spec; unsigned int i, j; + /* Update local and remote oids*/ + git_vector_foreach(&push->specs, i, spec) { if (spec->lref) { + /* This is a create or update. Local ref must exist. */ if (git_reference_name_to_id( &spec->loid, push->repo, spec->lref) < 0) { giterr_set(GIT_ENOTFOUND, "No such reference '%s'", spec->lref); return -1; } + } - if (!spec->rref) { - /* - * No remote reference given; if we find a remote - * reference with the same name we will update it, - * otherwise a new reference will be created. - */ - git_vector_foreach(&push->remote->refs, j, head) { - if (!strcmp(spec->lref, head->name)) { - /* - * Update remote reference - */ - git_oid_cpy(&spec->roid, &head->oid); - - break; - } - } - } else { - /* - * Remote reference given; update the given - * reference or create it. - */ - git_vector_foreach(&push->remote->refs, j, head) { - if (!strcmp(spec->rref, head->name)) { - /* - * Update remote reference - */ - git_oid_cpy(&spec->roid, &head->oid); - - break; - } + if (spec->rref) { + /* Remote ref may or may not (e.g. during create) already exist. */ + git_vector_foreach(&push->remote->refs, j, head) { + if (!strcmp(spec->rref, head->name)) { + git_oid_cpy(&spec->roid, &head->oid); + break; } } } diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index a73315975..34f0f8449 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -499,61 +499,25 @@ on_error: static int gen_pktline(git_buf *buf, git_push *push) { - git_remote_head *head; push_spec *spec; - unsigned int i, j, len; - char hex[41]; hex[40] = '\0'; + size_t i, len; + char old_id[41], new_id[41]; + + old_id[40] = '\0'; new_id[40] = '\0'; git_vector_foreach(&push->specs, i, spec) { - len = 2*GIT_OID_HEXSZ + 7; + len = 2*GIT_OID_HEXSZ + 7 + strlen(spec->rref); if (i == 0) { - len +=1; /* '\0' */ + ++len; /* '\0' */ if (push->report_status) len += strlen(GIT_CAP_REPORT_STATUS); } - if (spec->lref) { - len += spec->rref ? strlen(spec->rref) : strlen(spec->lref); + git_oid_fmt(old_id, &spec->roid); + git_oid_fmt(new_id, &spec->loid); - if (git_oid_iszero(&spec->roid)) { - - /* - * Create remote reference - */ - git_oid_fmt(hex, &spec->loid); - git_buf_printf(buf, "%04x%s %s %s", len, - GIT_OID_HEX_ZERO, hex, - spec->rref ? spec->rref : spec->lref); - - } else { - - /* - * Update remote reference - */ - git_oid_fmt(hex, &spec->roid); - git_buf_printf(buf, "%04x%s ", len, hex); - - git_oid_fmt(hex, &spec->loid); - git_buf_printf(buf, "%s %s", hex, - spec->rref ? spec->rref : spec->lref); - } - } else { - /* - * Delete remote reference - */ - git_vector_foreach(&push->remote->refs, j, head) { - if (!strcmp(spec->rref, head->name)) { - len += strlen(spec->rref); - - git_oid_fmt(hex, &head->oid); - git_buf_printf(buf, "%04x%s %s %s", len, - hex, GIT_OID_HEX_ZERO, head->name); - - break; - } - } - } + git_buf_printf(buf, "%04x%s %s %s", len, old_id, new_id, spec->rref); if (i == 0) { git_buf_putc(buf, '\0'); @@ -563,6 +527,7 @@ static int gen_pktline(git_buf *buf, git_push *push) git_buf_putc(buf, '\n'); } + git_buf_puts(buf, "0000"); return git_buf_oom(buf) ? -1 : 0; } diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d8ee4c2ee..9d949b77b 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -451,6 +451,7 @@ void test_online_push__delete(void) const char *specs_del_fake[] = { ":refs/heads/fake" }; /* Force has no effect for delete. */ const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; + push_status exp_stats_fake[] = { { "refs/heads/fake", NULL } }; const char *specs_delete[] = { ":refs/heads/tgt1" }; push_status exp_stats_delete[] = { { "refs/heads/tgt1", NULL } }; @@ -462,15 +463,18 @@ void test_online_push__delete(void) exp_stats1, ARRAY_SIZE(exp_stats1), exp_refs1, ARRAY_SIZE(exp_refs1), 0); - /* Deleting a non-existent branch should fail before the request is sent to - * the server because the client cannot find the old oid for the ref. + /* When deleting a non-existent branch, the git client sends zero for both + * the old and new commit id. This should succeed on the server with the + * same status report as if the branch were actually deleted. The server + * returns a warning on the side-band iff the side-band is supported. + * Since libgit2 doesn't support the side-band yet, there are no warnings. */ do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), - NULL, 0, - exp_refs1, ARRAY_SIZE(exp_refs1), -1); + exp_stats_fake, 1, + exp_refs1, ARRAY_SIZE(exp_refs1), 0); do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), - NULL, 0, - exp_refs1, ARRAY_SIZE(exp_refs1), -1); + exp_stats_fake, 1, + exp_refs1, ARRAY_SIZE(exp_refs1), 0); /* Delete one of the pushed branches. */ do_push(specs_delete, ARRAY_SIZE(specs_delete), From 43464497ab06f70117bcf98c95bc287de85121ad Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Thu, 3 Jan 2013 22:24:10 +0000 Subject: [PATCH 31/37] Add full license notice to bsearch code The original BSD glibc code contains the notice as given at http://opensource.apple.com/source/gcc/gcc-5666.3/libiberty/bsearch.c and should be given in full along with the code. --- src/util.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/util.c b/src/util.c index ba849aa1a..e89021458 100644 --- a/src/util.c +++ b/src/util.c @@ -438,6 +438,30 @@ uint32_t git__hash(const void *key, int len, uint32_t seed) * * Copyright (c) 1990 Regents of the University of California. * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. [rescinded 22 July 1999] + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ int git__bsearch( void **array, From 9651fdc29715543ec2d094a24ba92688bdfb7d76 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Thu, 3 Jan 2013 22:28:59 +0000 Subject: [PATCH 32/37] Give proper license notice to code from Android The usage of the Android derrived code contains a full notice which must be provided with the source code as per the terms given at: https://android.googlesource.com/platform/bionic/+/android-4.0.3_r1.1/libc/bionic/dirname_r.c --- src/path.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/path.c b/src/path.c index 1b1f554c7..fc8892a6e 100644 --- a/src/path.c +++ b/src/path.c @@ -39,7 +39,33 @@ static bool looks_like_network_computer_name(const char *path, int pos) /* * Based on the Android implementation, BSD licensed. - * Check http://android.git.kernel.org/ + * http://android.git.kernel.org/ + * + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ int git_path_basename_r(git_buf *buffer, const char *path) { From 5a62d659bcd3dd529fde9ab7eae2e216cba055cf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 3 Jan 2013 12:44:09 -0600 Subject: [PATCH 33/37] MERGE_HEAD contents iterator --- include/git2/errors.h | 1 + include/git2/repository.h | 16 ++++ src/merge.c | 53 +++++++++++++ src/merge.h | 1 + tests-clar/merge/setup.c | 159 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 tests-clar/merge/setup.c diff --git a/include/git2/errors.h b/include/git2/errors.h index 8ca900969..4eb9e94ef 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -64,6 +64,7 @@ typedef enum { GITERR_STASH, GITERR_CHECKOUT, GITERR_FETCHHEAD, + GITERR_MERGE, } git_error_t; /** diff --git a/include/git2/repository.h b/include/git2/repository.h index 02e689111..1371d5409 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -517,6 +517,22 @@ GIT_EXTERN(int) git_repository_fetchhead_foreach(git_repository *repo, git_repository_fetchhead_foreach_cb callback, void *payload); +typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid, + void *payload); + +/** + * If a merge is in progress, call callback 'cb' for each commit ID in the + * MERGE_HEAD file. + * + * @param repo A repository object + * @param callback Callback function + * @param apyload Pointer to callback data (optional) + * @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error + */ +GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, + git_repository_mergehead_foreach_cb callback, + void *payload); + /** * Calculate hash of file using repository filtering rules. * diff --git a/src/merge.c b/src/merge.c index dfdadca81..f52c112c9 100644 --- a/src/merge.c +++ b/src/merge.c @@ -241,3 +241,56 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l *out = result; return 0; } + +int git_repository_mergehead_foreach(git_repository *repo, + git_repository_mergehead_foreach_cb cb, + void *payload) +{ + git_buf merge_head_path = GIT_BUF_INIT, merge_head_file = GIT_BUF_INIT; + char *buffer, *line; + size_t line_num = 1; + git_oid oid; + int error = 0; + + assert(repo && cb); + + if ((error = git_buf_joinpath(&merge_head_path, repo->path_repository, + GIT_MERGE_HEAD_FILE)) < 0) + return error; + + if ((error = git_futils_readbuffer(&merge_head_file, + git_buf_cstr(&merge_head_path))) < 0) + goto cleanup; + + buffer = merge_head_file.ptr; + + while ((line = git__strsep(&buffer, "\n")) != NULL) { + if (strlen(line) != GIT_OID_HEXSZ) { + giterr_set(GITERR_INVALID, "Unable to parse OID - invalid length"); + error = -1; + goto cleanup; + } + + if ((error = git_oid_fromstr(&oid, line)) < 0) + goto cleanup; + + if (cb(&oid, payload) < 0) { + error = GIT_EUSER; + goto cleanup; + } + + ++line_num; + } + + if (*buffer) { + giterr_set(GITERR_MERGE, "No EOL at line %d", line_num); + error = -1; + goto cleanup; + } + +cleanup: + git_buf_free(&merge_head_path); + git_buf_free(&merge_head_file); + + return error; +} diff --git a/src/merge.h b/src/merge.h index af24de474..03b41e388 100644 --- a/src/merge.h +++ b/src/merge.h @@ -10,6 +10,7 @@ #include "git2/types.h" #include "git2/merge.h" #include "commit_list.h" +#include "vector.h" #define GIT_MERGE_MSG_FILE "MERGE_MSG" #define GIT_MERGE_MODE_FILE "MERGE_MODE" diff --git a/tests-clar/merge/setup.c b/tests-clar/merge/setup.c new file mode 100644 index 000000000..d88b2d94c --- /dev/null +++ b/tests-clar/merge/setup.c @@ -0,0 +1,159 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "merge.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "testrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452" + +#define THEIRS_SIMPLE_BRANCH "branch" +#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" + +#define OCTO1_BRANCH "octo1" +#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061" + +#define OCTO2_BRANCH "octo2" +#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c" + +#define OCTO3_BRANCH "octo3" +#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272" + +#define OCTO4_BRANCH "octo4" +#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae" + +#define OCTO5_BRANCH "octo5" +#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f" + +// Fixture setup and teardown +void test_merge_setup__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_setup__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static bool test_file_contents(const char *filename, const char *expected) +{ + git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT; + bool equals; + + git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename); + + cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr)); + equals = (strcmp(file_buf.ptr, expected) == 0); + + git_buf_free(&file_path_buf); + git_buf_free(&file_buf); + + return equals; +} + +static void write_file_contents(const char *filename, const char *output) +{ + git_buf file_path_buf = GIT_BUF_INIT; + + git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename); + cl_git_rewritefile(file_path_buf.ptr, output); + + git_buf_free(&file_path_buf); +} + +struct merge_head_cb_data { + const char **oid_str; + unsigned int len; + + unsigned int i; +}; + +int merge_head_foreach_cb(git_oid *oid, void *payload) +{ + git_oid expected_oid; + + struct merge_head_cb_data *cb_data = payload; + + git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]); + + cl_assert(git_oid_cmp(&expected_oid, oid) == 0); + + cb_data->i++; + + return 0; +} + +void test_merge_setup__head_notfound(void) +{ + int error; + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == GIT_ENOTFOUND); +} + +void test_merge_setup__head_invalid_oid(void) +{ + int error; + + write_file_contents(GIT_MERGE_HEAD_FILE, "invalid-oid\n"); + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == -1); +} + +void test_merge_setup__head_foreach_nonewline(void) +{ + int error; + + write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID); + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == -1); +} + +void test_merge_setup__head_foreach_one(void) +{ + const char *expected = THEIRS_SIMPLE_OID; + + struct merge_head_cb_data cb_data = { &expected, 1 }; + + write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n"); + + cl_git_pass(git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, &cb_data)); + + cl_assert(cb_data.i == cb_data.len); +} + +void test_merge_setup__head_foreach_octopus(void) +{ + const char *expected[] = { THEIRS_SIMPLE_OID, + OCTO1_OID, OCTO2_OID, OCTO3_OID, OCTO4_OID, OCTO5_OID }; + + struct merge_head_cb_data cb_data = { expected, 6 }; + + write_file_contents(GIT_MERGE_HEAD_FILE, + THEIRS_SIMPLE_OID "\n" + OCTO1_OID "\n" + OCTO2_OID "\n" + OCTO3_OID "\n" + OCTO4_OID "\n" + OCTO5_OID "\n"); + + cl_git_pass(git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, &cb_data)); + + cl_assert(cb_data.i == cb_data.len); +} From 10aa44cee2ed0523875f8da4410fc3c2c7ba8722 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Thu, 3 Jan 2013 23:42:04 +0000 Subject: [PATCH 34/37] Add Brian Downing to the hall of fame --- AUTHORS | 1 + git.git-authors | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 7f6ea7756..b9ae2f41b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,6 +9,7 @@ Ankur Sethi Ben Noordhuis Ben Straub Benjamin C Meyer +Brian Downing Brian Lopez Carlos Martín Nieto Colin Timmermans diff --git a/git.git-authors b/git.git-authors index 591ffecf3..f4b1e6712 100644 --- a/git.git-authors +++ b/git.git-authors @@ -41,6 +41,7 @@ ok Adam Simpkins (http transport) ok Andreas Ericsson ok Boyd Lynn Gerber +ok Brian Downing ok Brian Gernhardt ok Christian Couder ok Daniel Barkalow From ed8fb8210dc02e604e905d9ebe54ec73a9c8d220 Mon Sep 17 00:00:00 2001 From: Ted Nyman Date: Thu, 3 Jan 2013 16:14:23 -0800 Subject: [PATCH 35/37] Add note in CONVENTIONS about inlined functions --- CONVENTIONS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 10d9c8644..1e909a3e8 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -159,4 +159,11 @@ GIT_END_DECL #endif ``` +## Inlined functions + +All inlined functions must be declared as: + +```C +GIT_INLINE(result_type) git_modulename_functionname(arg_list); +``` From d0ae8b98de561abe59652f904a24f381c856dee6 Mon Sep 17 00:00:00 2001 From: Ted Nyman Date: Thu, 3 Jan 2013 16:15:52 -0800 Subject: [PATCH 36/37] Remove whitespace From a7ffd936bf26f6c7bb0a1d1dee811ace2c1c848e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 4 Jan 2013 17:46:38 +0100 Subject: [PATCH 37/37] clar: fix merge/setup.c --- tests-clar/merge/setup.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/tests-clar/merge/setup.c b/tests-clar/merge/setup.c index d88b2d94c..946c67e7b 100644 --- a/tests-clar/merge/setup.c +++ b/tests-clar/merge/setup.c @@ -44,22 +44,6 @@ void test_merge_setup__cleanup(void) cl_git_sandbox_cleanup(); } -static bool test_file_contents(const char *filename, const char *expected) -{ - git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT; - bool equals; - - git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename); - - cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr)); - equals = (strcmp(file_buf.ptr, expected) == 0); - - git_buf_free(&file_path_buf); - git_buf_free(&file_buf); - - return equals; -} - static void write_file_contents(const char *filename, const char *output) { git_buf file_path_buf = GIT_BUF_INIT; @@ -77,18 +61,14 @@ struct merge_head_cb_data { unsigned int i; }; -int merge_head_foreach_cb(git_oid *oid, void *payload) +static int merge_head_foreach_cb(const git_oid *oid, void *payload) { git_oid expected_oid; - struct merge_head_cb_data *cb_data = payload; git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]); - cl_assert(git_oid_cmp(&expected_oid, oid) == 0); - cb_data->i++; - return 0; }