From 7007e788bedbf82d590cb7c1cb40a814d569c1be Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 14 Jan 2018 13:51:01 +0100 Subject: [PATCH 01/11] Add django as a requirement to the linter Obviously it is needed when generating the sql through the sqlmigrate command --- setup.py | 2 +- .../test_project_rename_table/test_project_rename_table/wsgi.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c8b2499..7c6ab81 100644 --- a/setup.py +++ b/setup.py @@ -26,12 +26,12 @@ except(IOError, ImportError): long_description = open('README.md').read() install_requirements = [ + 'django>=1.10', ] test_requirements = [ 'pytest', 'tox', - 'django>=1.10', 'django-fake-database-backends', ] diff --git a/tests/test_project_fixtures/test_project_rename_table/test_project_rename_table/wsgi.py b/tests/test_project_fixtures/test_project_rename_table/test_project_rename_table/wsgi.py index 6741b31..96d3e60 100644 --- a/tests/test_project_fixtures/test_project_rename_table/test_project_rename_table/wsgi.py +++ b/tests/test_project_fixtures/test_project_rename_table/test_project_rename_table/wsgi.py @@ -11,6 +11,6 @@ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project_add_not_null_column.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project_rename_table.settings") application = get_wsgi_application() From e4880c5600465c70a33b407f65b59997d0a59291 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sun, 14 Jan 2018 15:50:58 +0100 Subject: [PATCH 02/11] Consider altering a column as backward incompatible * Resolves #9 * With test * For mysql only currently --- django_migration_linter/sql_analyser.py | 4 + tests/fixtures.py | 2 + tests/functional/test_migration_linter.py | 25 ++-- .../test_project_alter_column/.gitignore | 3 + .../test_project_alter_column/manage.py | 22 ++++ .../test_app/__init__.py | 0 .../test_app/admin.py | 3 + .../test_app/apps.py | 5 + .../test_app/migrations/0001_initial.py | 21 +++ .../test_app/migrations/0002_alter_column.py | 18 +++ .../test_app/migrations/__init__.py | 0 .../test_app/models.py | 4 + .../test_app/tests.py | 3 + .../test_app/views.py | 3 + .../test_project_alter_column/__init__.py | 0 .../test_project_alter_column/settings.py | 120 ++++++++++++++++++ .../test_project_alter_column/urls.py | 21 +++ .../test_project_alter_column/wsgi.py | 16 +++ 18 files changed, 260 insertions(+), 10 deletions(-) create mode 100644 tests/test_project_fixtures/test_project_alter_column/.gitignore create mode 100644 tests/test_project_fixtures/test_project_alter_column/manage.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/__init__.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/admin.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/apps.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0001_initial.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0002_alter_column.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/migrations/__init__.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/models.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/tests.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_app/views.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/__init__.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/settings.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/urls.py create mode 100644 tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/wsgi.py diff --git a/django_migration_linter/sql_analyser.py b/django_migration_linter/sql_analyser.py index d566072..7699aeb 100644 --- a/django_migration_linter/sql_analyser.py +++ b/django_migration_linter/sql_analyser.py @@ -50,6 +50,10 @@ migration_tests = ( 'fn': lambda sql, **kw: re.search('RENAME TABLE', sql) or re.search('ALTER TABLE .* RENAME TO', sql), 'err_msg': 'RENAMING tables' + }, { + 'code': 'ALTER_COLUMN', + 'fn': lambda sql, **kw: re.search('ALTER TABLE .* MODIFY', sql), + 'err_msg': 'ALTERING columns' }, { 'code': '', 'fn': has_default, diff --git a/tests/fixtures.py b/tests/fixtures.py index 2502885..5dd202b 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -28,6 +28,8 @@ DROP_COLUMN_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_project_drop_column/') RENAME_COLUMN_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_project_rename_column/') +ALTER_COLUMN_PROJECT = os.path.join( + _FIXTURES_FOLDER, 'test_project_alter_column') RENAME_TABLE_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_project_rename_table/') ADD_NOT_NULL_COLUMN_FOLLOWED_BY_DEFAULT_PROJECT = os.path.join( diff --git a/tests/functional/test_migration_linter.py b/tests/functional/test_migration_linter.py index 17f6afc..6187613 100644 --- a/tests/functional/test_migration_linter.py +++ b/tests/functional/test_migration_linter.py @@ -25,6 +25,17 @@ class BackwardcompatibilityDetectionTest(unittest.TestCase): BackwardcompatibilityDetectionTest, self).tearDown(*args, **kwargs) + def _test_linter_finds_errors(self, path, commit_id=None): + linter = MigrationLinter(path) + linter.lint_all_migrations(git_commit_id=commit_id) + self.assertTrue(linter.has_errors) + + def _test_linter_finds_no_errors(self, path, commit_id=None): + linter = MigrationLinter(path) + linter.lint_all_migrations(git_commit_id=commit_id) + self.assertFalse(linter.has_errors) + + # *** Tests *** def test_create_table_with_not_null_column(self): test_project_path = fixtures.CREATE_TABLE_WITH_NOT_NULL_COLUMN_PROJECT self._test_linter_finds_no_errors(test_project_path) @@ -50,6 +61,10 @@ class BackwardcompatibilityDetectionTest(unittest.TestCase): fixtures.ADD_NOT_NULL_COLUMN_FOLLOWED_BY_DEFAULT_PROJECT self._test_linter_finds_no_errors(test_project_path) + def test_detect_alter_column(self): + test_project_path = fixtures.ALTER_COLUMN_PROJECT + self._test_linter_finds_errors(test_project_path) + def test_no_specify_git_hash(self): test_project_path = fixtures.MULTI_COMMIT_PROJECT fixtures.prepare_git_project(test_project_path) @@ -66,13 +81,3 @@ class BackwardcompatibilityDetectionTest(unittest.TestCase): # test_project_path = fixtures.MULTI_COMMIT_PROJECT # fixtures.prepare_git_project(test_project_path) # self._test_linter_finds_no_errors(test_project_path, commit_id='tag1') - - def _test_linter_finds_errors(self, path, commit_id=None): - linter = MigrationLinter(path) - linter.lint_all_migrations(git_commit_id=commit_id) - self.assertTrue(linter.has_errors) - - def _test_linter_finds_no_errors(self, path, commit_id=None): - linter = MigrationLinter(path) - linter.lint_all_migrations(git_commit_id=commit_id) - self.assertFalse(linter.has_errors) diff --git a/tests/test_project_fixtures/test_project_alter_column/.gitignore b/tests/test_project_fixtures/test_project_alter_column/.gitignore new file mode 100644 index 0000000..63973d0 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/.gitignore @@ -0,0 +1,3 @@ +*.pyc +__pycache__/ +*sqlite3 diff --git a/tests/test_project_fixtures/test_project_alter_column/manage.py b/tests/test_project_fixtures/test_project_alter_column/manage.py new file mode 100644 index 0000000..c1ee174 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project_alter_column.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/__init__.py b/tests/test_project_fixtures/test_project_alter_column/test_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/admin.py b/tests/test_project_fixtures/test_project_alter_column/test_app/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/apps.py b/tests/test_project_fixtures/test_project_alter_column/test_app/apps.py new file mode 100644 index 0000000..fc04070 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TestAppConfig(AppConfig): + name = 'test_app' diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0001_initial.py b/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0001_initial.py new file mode 100644 index 0000000..faf8b51 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0001_initial.py @@ -0,0 +1,21 @@ +# Generated by Django 2.0.1 on 2018-01-14 12:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='A', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=10, null=True)), + ], + ), + ] diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0002_alter_column.py b/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0002_alter_column.py new file mode 100644 index 0000000..4292dd0 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/0002_alter_column.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.1 on 2018-01-14 12:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('test_app', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='a', + name='code', + field=models.IntegerField(null=True), + ), + ] diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/__init__.py b/tests/test_project_fixtures/test_project_alter_column/test_app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/models.py b/tests/test_project_fixtures/test_project_alter_column/test_app/models.py new file mode 100644 index 0000000..d4b75cf --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/models.py @@ -0,0 +1,4 @@ +from django.db import models + +class A(models.Model): + code = models.IntegerField(null=True) diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/tests.py b/tests/test_project_fixtures/test_project_alter_column/test_app/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/tests/test_project_fixtures/test_project_alter_column/test_app/views.py b/tests/test_project_fixtures/test_project_alter_column/test_app/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_app/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/__init__.py b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/settings.py b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/settings.py new file mode 100644 index 0000000..7d04288 --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/settings.py @@ -0,0 +1,120 @@ +""" +Django settings for test_project_alter_column project. + +Generated by 'django-admin startproject' using Django 1.11.6. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'gtb+mohs%gf0+#fr89vw7e&#edmv=q8!iv+n&j_soawk$tkj3^' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'test_app' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'test_project_alter_column.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'test_project_alter_column.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django_fake_database_backends.backends.mysql' + } +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/urls.py b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/urls.py new file mode 100644 index 0000000..735de5d --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/urls.py @@ -0,0 +1,21 @@ +"""linter_test_project URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] diff --git a/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/wsgi.py b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/wsgi.py new file mode 100644 index 0000000..749e98c --- /dev/null +++ b/tests/test_project_fixtures/test_project_alter_column/test_project_alter_column/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for linter_test_project project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project_alter_column.settings") + +application = get_wsgi_application() From 1fca277fc26d36b9823f1eaff4256751af96ab6b Mon Sep 17 00:00:00 2001 From: Felix Bauer Date: Wed, 17 Jan 2018 10:59:58 +0100 Subject: [PATCH 03/11] Add test example --- examples/example_test_integration.py | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 examples/example_test_integration.py diff --git a/examples/example_test_integration.py b/examples/example_test_integration.py new file mode 100644 index 0000000..5cfd59f --- /dev/null +++ b/examples/example_test_integration.py @@ -0,0 +1,72 @@ +# Copyright 2018 3YOURMIND GmbH + +# 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. + +# +# You can use this file to integrate the migration-linter into your tests. +# In this example only the migrations after the latest version bump are +# considered. +# + +import os +from subprocess import Popen, PIPE +from unittest import TestCase + +from django.conf import settings + + +# Replace that function according to your needs +def read_version_file(): + with open('version', 'r') as f: + return '{0}'.format(f.read().replace('\n', '')) + + +class MigrationTest(TestCase): + ignored_migrations = ( + ) + excluded_apps = ( + ) + + @classmethod + def setUpClass(cls): + super(MigrationTest, cls).setUpClass() + cls.project_path = os.path.dirname(settings.PROJECT_PATH) + cls.latest_tag = '{0}'.format(read_version_file()) + + def test_latest_migrations(self): + ignored_migration_parameter = '--ignore-name ' + \ + ' '.join(self.ignored_migrations) \ + if self.ignored_migrations else '' + + excluded_apps_parameter = '--exclude-apps ' + \ + ' '.join(self.excluded_apps) \ + if self.excluded_apps else '' + + linter_cmd = 'django-migration-linter {0} {1} {2} {3}'.format( + self.project_path, + self.latest_tag, + ignored_migration_parameter, + excluded_apps_parameter) + + lint_process = Popen(linter_cmd, shell=True, stdout=PIPE, stderr=PIPE) + lint_process.wait() + + if lint_process.returncode != 0: + out, err = lint_process.communicate() + out = out.decode('ascii') + self.fail('The migration linter found errors\n' + 'migration command: {0}\n' + 'STDOUT: {1}\n' + 'STDERR: {2}\n'. + format(linter_cmd, out, err) + ) From 59ba4cc1ea23cd97e932ee2de2eef7142cc98c81 Mon Sep 17 00:00:00 2001 From: Felix Bauer Date: Mon, 15 Jan 2018 15:02:06 +0100 Subject: [PATCH 04/11] Add README.rst --- README.rst | 8 ++++++++ setup.py | 6 +----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..fb8f092 --- /dev/null +++ b/README.rst @@ -0,0 +1,8 @@ +Django migration linter +======================= + +Detect backward incompatible migrations for your django project. It will save you time by making sure migrations will not break anything. + +`The source and README for this project is available here +`_. + diff --git a/setup.py b/setup.py index 7c6ab81..a400095 100644 --- a/setup.py +++ b/setup.py @@ -19,11 +19,7 @@ from setuptools import setup, find_packages PROJECT_DIR = path.abspath(path.dirname(__file__)) -try: - import pypandoc - long_description = pypandoc.convert('README.md', 'rst') -except(IOError, ImportError): - long_description = open('README.md').read() +long_description = open('README.rst').read() install_requirements = [ 'django>=1.10', From 3e27f117ba18eb75d34972bef7cf4b0d061ce069 Mon Sep 17 00:00:00 2001 From: David Wobrock Date: Wed, 17 Jan 2018 17:27:38 +0100 Subject: [PATCH 05/11] Migrate the complete readme to reStructuredText --- README.md | 61 ----------------------------------------------- README.rst | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- setup.py | 4 ++-- 3 files changed, 69 insertions(+), 65 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index d41e828..0000000 --- a/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Django migration linter - -> Detect backward incompatible migrations for your django project. It will save you time by making sure migrations will not break anything. - -badge of travis CI -PyPi version -badge of license -badge of pull request welcome -badge of hiring advertisement of 3yourmind -badge of github star - -## Dependencies - -

- Needed software (in PATH) - - * `python` - * `git` (if you specify a git identifier) -

- -The linter will try to detect if the project is a django project and is versioned with git. - -## Installation - -

Using pip -
pip install django-migration-linter
-

- -## Usage - -`django-migration-linter DJANGO_PROJECT_FOLDER [GIT_COMMIT_ID] [--ignore-name-contains=IGNORE_NAME_CONTAINS] [--include-apps INCLUDE_APPS [INCLUDE_APPS ...] | --exclude-apps EXCLUDE_APPS [EXCLUDE_APPS ...]]` - -| Parameter | Description | -| -- | -- | -| `DJANGO_PROJECT_FOLDER` | An absolute or relative path to the django project. | -| `GIT_COMMIT_ID` | If specified, only migrations since this commit will be taken into account. If not specified, the initial repo commit will be used. | -| `--ignore-name-contains IGNORE_NAME_CONTAINS` | Ignore migrations containing this name | -| `--ignore-name IGNORE_NAME [IGNORE_NAME ...]` | Ignore migrations with exactly one of these names | -| `--include-apps INCLUDE_APPS [INCLUDE_APPS ...]` | Check only migrations that are in the specified django apps | -| `--exclude-apps EXCLUDE_APPS [EXCLUDE_APPS ...]` | Ignore migrations that are in the specified django apps | -| `--verbose` or `-v` | print more information during execution | -| `--database DATABASE` | Specify the database for which to generate the SQL. Defaults to *default* | - -## Examples - -3YOURMIND is running this on [Bitbucket Pipelines](https://bitbucket.org/product/features/pipelines) with every build getting triggered in this environment. - -![](https://i.imgur.com/ocLpQXP.png) - -## Tests - -The easiest way to run the tests is to invoke [tox](https://pypi.python.org/pypi/tox). - -## Contributing - -First, thank you very much if you want to contribute to the project. -Please base your work on the `dev` branch and also target this branch in your pull request. - -## License - -*django-migration-linter* is released under the [Apache 2.0 License](./LICENSE). diff --git a/README.rst b/README.rst index fb8f092..30875a0 100644 --- a/README.rst +++ b/README.rst @@ -1,8 +1,73 @@ +======================= Django migration linter ======================= Detect backward incompatible migrations for your django project. It will save you time by making sure migrations will not break anything. -`The source and README for this project is available here -`_. +.. image:: https://travis-ci.org/3YOURMIND/django-migration-linter.svg?branch=master + :target: https://travis-ci.org/3YOURMIND/django-migration-linter +.. image:: https://img.shields.io/pypi/v/django-migration-linter.svg + :target: https://pypi.python.org/pypi/django-migration-linter/ + +.. image:: https://img.shields.io/github/license/3yourmind/django-migration-linter.svg + :target: ./LICENSE + +.. image:: https://img.shields.io/badge/PR-welcome-green.svg + :target: https://github.com/3YOURMIND/django-migration-linter/pulls + +.. image:: https://img.shields.io/badge/3YOURMIND-Hiring-brightgreen.svg + :target: https://www.3yourmind.com/career + +.. image:: https://img.shields.io/github/stars/3YOURMIND/django-migration-linter.svg?style=social&label=Stars + :target: https://github.com/3YOURMIND/django-migration-linter/stargazers + +Installation +------------ + +``pip install django-migration-linter`` + + +Usage +----- + +``django-migration-linter DJANGO_PROJECT_FOLDER [GIT_COMMIT_ID] [--ignore-name-contains=IGNORE_NAME_CONTAINS] [--include-apps INCLUDE_APPS [INCLUDE_APPS ...] | --exclude-apps EXCLUDE_APPS [EXCLUDE_APPS ...]]`` + +================================================== =========================================================================================================================== + Parameter Description +================================================== =========================================================================================================================== +``DJANGO_PROJECT_FOLDER`` An absolute or relative path to the django project. +``GIT_COMMIT_ID`` If specified, only migrations since this commit will be taken into account. If not specified, all migrations will be linted. +``--ignore-name-contains IGNORE_NAME_CONTAINS`` Ignore migrations containing this name. +``--ignore-name IGNORE_NAME [IGNORE_NAME ...]`` Ignore migrations with exactly one of these names. +``--include-apps INCLUDE_APPS [INCLUDE_APPS ...]`` Check only migrations that are in the specified django apps. +``--exclude-apps EXCLUDE_APPS [EXCLUDE_APPS ...]`` Ignore migrations that are in the specified django apps. +``--verbose or -v`` Print more information during execution. +``--database DATABASE`` Specify the database for which to generate the SQL. Defaults to *default*. +================================================== =========================================================================================================================== + +Examples +-------- + +3YOURMIND is running the linter on `Bitbucket Pipelines`_ on every build getting pushed. + +Tests +----- + +The easiest way to run the tests is to invoke `tox`_. + +Contributing +------------ + +First, thank you very much if you want to contribute to the project. +Please base your work on the ``dev`` branch and also target this branch in your pull request. + +License +------- + +*django-migration-linter* is released under the `Apache 2.0 License`_. + + +.. _`Bitbucket Pipelines`: https://bitbucket.org/product/features/pipelines +.. _`tox`: https://pypi.python.org/pypi/tox +.. _`Apache 2.0 License`: https://github.com/3YOURMIND/django-migration-linter/blob/master/LICENSE diff --git a/setup.py b/setup.py index a400095..0f78d53 100644 --- a/setup.py +++ b/setup.py @@ -12,14 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -from codecs import open from os import path from setuptools import setup, find_packages PROJECT_DIR = path.abspath(path.dirname(__file__)) -long_description = open('README.rst').read() +with open(path.join(PROJECT_DIR, 'README.rst')) as f: + long_description = f.read() install_requirements = [ 'django>=1.10', From 5bef4e7a172ff0da50ca09dbb5a00c9afdaf49db Mon Sep 17 00:00:00 2001 From: Felix Bauer Date: Mon, 15 Jan 2018 18:02:24 +0100 Subject: [PATCH 06/11] Only consider added migrations --- django_migration_linter/migration_linter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 69158ff..fcf8e2d 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -152,16 +152,16 @@ class MigrationLinter(object): def _gather_migrations_git(self, git_commit_id): migrations = [] # Get changes since specified commit - git_diff_command = 'cd {0} && git diff --name-only {1}'.format( + git_diff_command = 'cd {0} && git diff --name-status {1}'.format( self.django_path, git_commit_id) log.info('Executing {0}'.format(git_diff_command)) diff_process = Popen( git_diff_command, shell=True, stdout=PIPE, stderr=PIPE) for line in map( utils.clean_bytes_to_str, diff_process.stdout.readlines()): - # Only gather lines that include migrations + # Only gather lines that include added migrations if re.search( - '\/{0}\/.*\.py'.format(self.MIGRATION_FOLDER_NAME), + '^A.*\/{0}\/.*\.py'.format(self.MIGRATION_FOLDER_NAME), line) and \ '__init__' not in line: app_name, migration_name = self._split_migration_path(line) From fffdf5714eed5a24e86f50f4526754cace186b25 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Thu, 18 Jan 2018 23:32:22 +0100 Subject: [PATCH 07/11] Fix that linter actually ignores deleted files and add a specific test for this --- django_migration_linter/migration_linter.py | 7 +- tests/fixtures.py | 5 +- tests/functional/test_cmd_line_call.py | 6 +- .../test_deleted_migration_project/.gitignore | 3 + .../git/COMMIT_EDITMSG | 1 + .../test_deleted_migration_project/git/HEAD | 1 + .../git/ORIG_HEAD | 1 + .../test_deleted_migration_project/git/config | 5 + .../git/description | 1 + .../test_deleted_migration_project/git/index | Bin 0 -> 1581 bytes .../git/info/exclude | 6 + .../git/logs/HEAD | 3 + .../git/logs/refs/heads/master | 3 + .../03/95cbee60f2ea1b97f42ebdd43991c8f5d8d76e | 2 + .../09/d00ce23e0b42f2c18895ee5fa577f57f14b2ac | 3 + .../10/7654971c8d8cd4a209b0363d4604fc9ee7d494 | Bin 0 -> 136 bytes .../15/4ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba | 1 + .../2b/df33777b398bff4fca0e0aad47e9a7c57a2f96 | 2 + .../3a/629de3fbf102d771b2a711bfe2f1ab3b830d14 | Bin 0 -> 462 bytes .../3c/dde4d6a3d85cb65c15446791e93c78ecac3ed5 | Bin 0 -> 173 bytes .../43/52f2dfe637a766c7fe558cc85b961860efd50c | Bin 0 -> 127 bytes .../45/3c549087e331a41ecbed2a81c9b8e92e8693e9 | Bin 0 -> 240 bytes .../49/ca6418f20f7dac5f12b1c1d66e99844d44fd12 | Bin 0 -> 126 bytes .../4b/825dc642cb6eb9a060e54bf8d69288fbee4904 | Bin 0 -> 15 bytes .../4c/e3b40413b7f8938d91828c437f33f66d57fcc9 | 1 + .../61/d7983b41623ed85d46c0212c66db9507948532 | 3 + .../63/973d01988ba594743a8046c9c88c2aa527d307 | Bin 0 -> 42 bytes .../73/47b0f2a9845fa268ad4a19967c706e5d7be38b | Bin 0 -> 296 bytes .../73/5de5db8bc5e1ed29b3cb7ece62b5e7c8db06ee | Bin 0 -> 391 bytes .../7c/e503c2dd97ba78597f6ff6e4393132753573f6 | Bin 0 -> 72 bytes .../86/deb0cf782231006446fd6194592c2243e74ffe | 1 + .../8c/38f3f3dad51e4585f3984282c2a4bec5349c1e | Bin 0 -> 77 bytes .../8e/2c3931324179d354f7f87a25e642778ed734f9 | Bin 0 -> 256 bytes .../91/ea44a218fbd2f408430959283f0419c921093e | Bin 0 -> 77 bytes .../92/8f9938db104a389b465923b8ea1fcce7b5c678 | Bin 0 -> 124 bytes .../94/bfbb751ce085f6afb8c5cca660727997cd4d83 | Bin 0 -> 1251 bytes .../af/646cefb7f45abb2612374156d130b37a875510 | Bin 0 -> 137 bytes .../b3/0169e7d9fe1fca0cb34f216bc89fd529814eaf | 3 + .../be/2fae887ee7ecd2d1e6371af1a865c17414bde9 | 1 + .../e0/00041da0b7dc84cb17be523882c118641b72b5 | 2 + .../e4/9014e99d282c96e97490f64f13dba56637acc3 | Bin 0 -> 240 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../f2/5c8d6c97ee9f2aa3ebc1884e9d374e2a93f8e7 | Bin 0 -> 173 bytes .../f7/9f238852ec7cd7b9a3cc7f6b9b5324d380ae8b | Bin 0 -> 111 bytes .../fc/04070e8336f17e3b2402586653623e6bb51f67 | Bin 0 -> 88 bytes .../git/refs/heads/master | 1 + .../test_deleted_migration_project/manage.py | 22 ++++ .../test_app/__init__.py | 0 .../test_app/admin.py | 3 + .../test_app/apps.py | 5 + .../test_app/migrations/0001_initial.py | 21 +++ .../migrations/0003_new_nullable_field.py | 18 +++ .../test_app/migrations/__init__.py | 0 .../test_app/models.py | 6 + .../test_app/tests.py | 3 + .../test_app/views.py | 3 + .../__init__.py | 0 .../settings.py | 120 ++++++++++++++++++ .../test_deleted_migration_project/urls.py | 21 +++ .../test_deleted_migration_project/wsgi.py | 16 +++ 60 files changed, 293 insertions(+), 7 deletions(-) create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/.gitignore create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/HEAD create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/ORIG_HEAD create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/config create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/description create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/index create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/info/exclude create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/logs/HEAD create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/03/95cbee60f2ea1b97f42ebdd43991c8f5d8d76e create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/09/d00ce23e0b42f2c18895ee5fa577f57f14b2ac create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/10/7654971c8d8cd4a209b0363d4604fc9ee7d494 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/15/4ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/2b/df33777b398bff4fca0e0aad47e9a7c57a2f96 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/3a/629de3fbf102d771b2a711bfe2f1ab3b830d14 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/3c/dde4d6a3d85cb65c15446791e93c78ecac3ed5 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/43/52f2dfe637a766c7fe558cc85b961860efd50c create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/45/3c549087e331a41ecbed2a81c9b8e92e8693e9 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/49/ca6418f20f7dac5f12b1c1d66e99844d44fd12 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/4c/e3b40413b7f8938d91828c437f33f66d57fcc9 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/61/d7983b41623ed85d46c0212c66db9507948532 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/63/973d01988ba594743a8046c9c88c2aa527d307 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/47b0f2a9845fa268ad4a19967c706e5d7be38b create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/5de5db8bc5e1ed29b3cb7ece62b5e7c8db06ee create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/7c/e503c2dd97ba78597f6ff6e4393132753573f6 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/86/deb0cf782231006446fd6194592c2243e74ffe create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/8c/38f3f3dad51e4585f3984282c2a4bec5349c1e create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/8e/2c3931324179d354f7f87a25e642778ed734f9 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/91/ea44a218fbd2f408430959283f0419c921093e create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/92/8f9938db104a389b465923b8ea1fcce7b5c678 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/94/bfbb751ce085f6afb8c5cca660727997cd4d83 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/af/646cefb7f45abb2612374156d130b37a875510 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/b3/0169e7d9fe1fca0cb34f216bc89fd529814eaf create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/be/2fae887ee7ecd2d1e6371af1a865c17414bde9 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/e0/00041da0b7dc84cb17be523882c118641b72b5 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/e4/9014e99d282c96e97490f64f13dba56637acc3 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/f2/5c8d6c97ee9f2aa3ebc1884e9d374e2a93f8e7 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/f7/9f238852ec7cd7b9a3cc7f6b9b5324d380ae8b create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/fc/04070e8336f17e3b2402586653623e6bb51f67 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/manage.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/__init__.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/admin.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/apps.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0001_initial.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/__init__.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/tests.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_app/views.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/__init__.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/settings.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/urls.py create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/wsgi.py diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index fcf8e2d..7ecbf98 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -125,16 +125,16 @@ class MigrationLinter(object): Even if calling a shell is slow and ugly, for now, it allows to seperate the instances correctly. """ - git_diff_command = ( + sqlmigrate_command = ( 'cd {0} && ' '{1} manage.py sqlmigrate {2} {3} ' '--database {4}').format( self.django_path, self.python_exe, app_name, migration_name, self.database) - log.info('Executing {0}'.format(git_diff_command)) + log.info('Executing {0}'.format(sqlmigrate_command)) sqlmigrate_process = Popen( - git_diff_command, shell=True, stdout=PIPE, stderr=PIPE) + sqlmigrate_command, shell=True, stdout=PIPE, stderr=PIPE) sql_statements = [] for line in map( @@ -164,6 +164,7 @@ class MigrationLinter(object): '^A.*\/{0}\/.*\.py'.format(self.MIGRATION_FOLDER_NAME), line) and \ '__init__' not in line: + line = line.split()[-1] # Remove the status letter app_name, migration_name = self._split_migration_path(line) migrations.append((app_name, migration_name)) diff_process.wait() diff --git a/tests/fixtures.py b/tests/fixtures.py index 5dd202b..5d97a82 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -38,6 +38,8 @@ MULTI_COMMIT_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_project_multi_commit/') CORRECT_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_correct_project/') +DELETED_MIGRATION_PROJECT = os.path.join( + _FIXTURES_FOLDER, 'test_deleted_migration_project/') NOT_DJANGO_GIT_PROJECT = os.path.join( _FIXTURES_FOLDER, 'test_git_project/') @@ -46,7 +48,8 @@ NOT_GIT_DJANGO_PROJECT = os.path.join( ALL_GIT_PROJECTS = ( NOT_DJANGO_GIT_PROJECT, - MULTI_COMMIT_PROJECT + MULTI_COMMIT_PROJECT, + DELETED_MIGRATION_PROJECT ) diff --git a/tests/functional/test_cmd_line_call.py b/tests/functional/test_cmd_line_call.py index bc34b15..ac62575 100644 --- a/tests/functional/test_cmd_line_call.py +++ b/tests/functional/test_cmd_line_call.py @@ -116,10 +116,10 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('IGNORE')) def test_call_linter_cmd_line_git_id(self): - cmd = '{0} {1} d7125d5f4f0cc9623f670a66c54f131acc50032d'.format( + cmd = '{0} {1} 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba'.format( self.linter_exec, - fixtures.MULTI_COMMIT_PROJECT) - fixtures.prepare_git_project(fixtures.MULTI_COMMIT_PROJECT) + fixtures.DELETED_MIGRATION_PROJECT) + fixtures.prepare_git_project(fixtures.DELETED_MIGRATION_PROJECT) process = Popen( cmd, shell=True, stdout=PIPE, stderr=PIPE) diff --git a/tests/test_project_fixtures/test_deleted_migration_project/.gitignore b/tests/test_project_fixtures/test_deleted_migration_project/.gitignore new file mode 100644 index 0000000..63973d0 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/.gitignore @@ -0,0 +1,3 @@ +*.pyc +__pycache__/ +*sqlite3 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG b/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG new file mode 100644 index 0000000..974dd96 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG @@ -0,0 +1 @@ +Delete file and insert new diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/HEAD b/tests/test_project_fixtures/test_deleted_migration_project/git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/ORIG_HEAD b/tests/test_project_fixtures/test_deleted_migration_project/git/ORIG_HEAD new file mode 100644 index 0000000..70acf6c --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/ORIG_HEAD @@ -0,0 +1 @@ +154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/config b/tests/test_project_fixtures/test_deleted_migration_project/git/config new file mode 100644 index 0000000..eeb8dd7 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/description b/tests/test_project_fixtures/test_deleted_migration_project/git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/index b/tests/test_project_fixtures/test_deleted_migration_project/git/index new file mode 100644 index 0000000000000000000000000000000000000000..b3e362d0e1ceeeda1718673cb37a52dd4f808748 GIT binary patch literal 1581 zcmZ?q402{*U|<4b{;0se8S2)B4`4JxGTzcu5C7J1Y`9-NPg;9yJTli)OT!7I)aiDqaGf~ZBwy{c@`}p@qrt5{9 zmJ9BG^l`OyGp`5(XKrF%VtT4xK_vsoJ^J4ZcED(`If9+?sOB&*Je&Jy_NI&1oV~j> z*Of=zIP|0^cp`&HNosLPd}2X?etdjpUS>&rJjh5efSCuQA?9{$L^IdE$KvznTUX^= zTR+cmYC5!J-%*n}atwlSa}!f?GxPAcQwq(zs6Q<1e9dMb>#S9nBGQ7B?6SAYr!xp3 z%qu7;2D>pTQEq}|!fFc`4fQuLE|BAc@u~KG!cSz+KRdBoB`CHJ!tmSY-Y@Se)FIF zDW1*#irFXTU)5~%ThE|}!ye=KywvjeywaSU#H5_m__WN_oD`^)!1U0=|9vM1DBKO6 zJ_OnWOc#Qk>ZtbNh);QJ_Mt{C&>spsYn`9KXsG$pXy%`t)IZbWwt$z#Y_~||9k1li zJl}e(frSd&Gk2R0WKNy5AVpJ|6EW`*)YhJZSy4 ze#g->%Mywzr=Rt0W*}r=acW6PW?niG;ctp+A2UaB?9tWsYhO-)T85zAwn4>7Yc4bkSCV_LLW= zXF~HqNRX>5(Cn!UhNcQeTsC)~Tw8o2W?PJ?OZvo@HWhEy*jq-(w#hHy@l?!UtYE;kJ|*Y<_AgPp)r8C)!!8l3@L7Z6Q@M#C^g{HN~e2+4&61Dlh%T)^i^cfw* literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/info/exclude b/tests/test_project_fixtures/test_deleted_migration_project/git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/logs/HEAD b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/HEAD new file mode 100644 index 0000000..236e554 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/HEAD @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e David-Wobrock 1516314144 +0100 commit (initial): Project init +0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba David-Wobrock 1516314322 +0100 commit: Add backward incompatible migration +154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba be2fae887ee7ecd2d1e6371af1a865c17414bde9 David-Wobrock 1516314457 +0100 commit: Delete file and insert new diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master new file mode 100644 index 0000000..236e554 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e David-Wobrock 1516314144 +0100 commit (initial): Project init +0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba David-Wobrock 1516314322 +0100 commit: Add backward incompatible migration +154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba be2fae887ee7ecd2d1e6371af1a865c17414bde9 David-Wobrock 1516314457 +0100 commit: Delete file and insert new diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/03/95cbee60f2ea1b97f42ebdd43991c8f5d8d76e b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/03/95cbee60f2ea1b97f42ebdd43991c8f5d8d76e new file mode 100644 index 0000000..0054e0e --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/03/95cbee60f2ea1b97f42ebdd43991c8f5d8d76e @@ -0,0 +1,2 @@ +x¥�; +1@­sŠéÅ%gC"ÀÎ:ŸY�kQ¯ïŠG°|¯x/I­¥z\õÆ �s²dR´}ÐVóHqrÙzãÜ™ÉkRáÙ¯Òà^%oΛ¤vù‹Ãû‡‡K å>$©{Àí ‰`­QkµØeÜù�„:5¹qêP¥«J>ñ \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/09/d00ce23e0b42f2c18895ee5fa577f57f14b2ac b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/09/d00ce23e0b42f2c18895ee5fa577f57f14b2ac new file mode 100644 index 0000000..4d7d160 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/09/d00ce23e0b42f2c18895ee5fa577f57f14b2ac @@ -0,0 +1,3 @@ +x]PËjÃ0ìÙ_±�ƒ�;Ôm øRrÈ­·„m­�ZY2zÒ¯¯dåY„˜™�™UÃee™?Ì }L¡•”‰~Öté«G¢¼£@U¤ÐaóU‹^B‘Eö RÀ2/^Ò"O—%O«¼Œ:% ¤³Æ*$Ø0JeÀ +æÌ‘pfœ×QÒÉ/£ÍY7°Þ…1)ô7à•QËk­a¦’«(»€óU�;L0Ãj|(‹£8¢ (Z†ÚŸ“ð89úí|à…ñ67o +Ýú{_&™&=ï�¨¬âu¼¸C;†œê*„a¸“˜Ñø¼U¶¶Fn½4©Ý‹´S­|錊 µ:’o<ž�ÊmÅ~±Úºßs’T�ÔHB‰Ý&žÏï{øÐ$–s2UºFï„ÁUH÷‚)ãÿüájwr>Dqá£& \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/10/7654971c8d8cd4a209b0363d4604fc9ee7d494 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/10/7654971c8d8cd4a209b0363d4604fc9ee7d494 new file mode 100644 index 0000000000000000000000000000000000000000..0d561f286a2694f6770b34a3aa94279bb1452edf GIT binary patch literal 136 zcmV;30C)d*0V^p=O;s>7He)a}FfcPQQ7|wtFpSU4%Ph%E%+V{TWYE5ETwZP2{onr- zAJn1;;y5hm6$H#+|J)8Sz_NI&1oV~j>*Of=zIP|0^cp?Cn@;MkC3PqX# literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/15/4ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/15/4ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba new file mode 100644 index 0000000..15253fb --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/15/4ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba @@ -0,0 +1 @@ +x¥ŽKJD1Eg5›ü^> ¢àWª*mèÎK¢½}Ÿ¸g÷ÜÁáÐè½-°Á>¬)Õn”8PŽ"¹ZD'…LJ^2»èÅbv5IT7œ²/Ð.oTD‚®VД«·R˜½ËÙPª'ŽA~­Ï1á¿?}Œ2]à™ñtÿÃ×sÇv=Ñè/`6œñÎZxÔFku¼Gè’(Ô3¤Ë'CÛå W+W�ÞÎó˜cW?hþVd \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/2b/df33777b398bff4fca0e0aad47e9a7c57a2f96 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/2b/df33777b398bff4fca0e0aad47e9a7c57a2f96 new file mode 100644 index 0000000..a150ce3 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/2b/df33777b398bff4fca0e0aad47e9a7c57a2f96 @@ -0,0 +1,2 @@ +x]OÁj„0ì9_ñ \QÙ‚,xXºlÙÃÞz+"Ѽ•´1‘D ö뛘ݵÛwafÞ̼F¨¶ÅËÓ3¼¡DMGdÐÌpø¤²S�'i’�’�§Y±I³MV@žïò-!­z`‹,a ð~Pz„žwÖƒ+ibèCa!­ ÆÀùF…«(¹ƒÑްÃ%9P»žÐc ” eËÑXâcVžSƒ+íùñªÑ^uveÂeÓñn$í± öAü€^8 +fJâ…þ ΂ÛUÉ~ÕÑICju»„°Ò•Žaм§z®¿p¾"µ½Šÿ`y¤ÂXÉ7êF¬}‰Ó!ˆ¢Ç.4 ä$D½TZ£OrĵOw‚%ãÿ~µÚ]�+ò ¢�m \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/3a/629de3fbf102d771b2a711bfe2f1ab3b830d14 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/3a/629de3fbf102d771b2a711bfe2f1ab3b830d14 new file mode 100644 index 0000000000000000000000000000000000000000..6c0751607a369ba9225b56a9e97d3c85c8d06064 GIT binary patch literal 462 zcmV;<0Wtn~0ew?VYui8&?ODHKDj(uNks+s02*K1QNoj3E+(S>xNE*qTYIn@;NJRg> zyDP^@=!XtM?7n&P-kVX`aS7K~*B@pd7rl3jQriXD0gj^_*k;-s*$J?J`SPRBGTneu z77Zx{H#d+gWl&qC^3NHBhkX$!v}0R%lA0RqJDKOJuglHdRz0rw`-jclqx!yG{rI-d zKS3_!Mb*@iP_2w^9g1eFj*g$Gl1L)jwm!d1^y0>;Pwdq=Hc&sIZMmq}QDM+xONOk# zNjyDM)eETzRTZ0ns8y#eB{q7l=qT`zjINzy_ews4{eb{W9_WS4;0O)s4jOjg*$}WC z$blpD!7r?>?;U|0P{M0!5p~W$d*25dAE8}0PLNen9#2iU4<p6I z;+X`8d_1s)U78bI6=%e|cw)&ZhAE^o?0>#vl|$|6Z7lP1X}pe4{)PLlwioB5CpQHw zLjoiBkfP9X;Xzw3!8O$o!iW4%DjY(nSau;#8*3fxe(vwLo85AM52tNPLmklRh`WVV z2q|{?3tJdYOJM*Z%S!Zs5~c`YBc;dgE!*w;+G)R{wd6jj{O9(}!>>@FYlqA1H(V$L E*C@2&^8f$< literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/3c/dde4d6a3d85cb65c15446791e93c78ecac3ed5 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/3c/dde4d6a3d85cb65c15446791e93c78ecac3ed5 new file mode 100644 index 0000000000000000000000000000000000000000..eee3f458163ffecedd400fe4f20c0c6097588067 GIT binary patch literal 173 zcmV;e08;;W0V^p=O;s>7GiNX~FfcPQQP4}zEXhpI%P&f0NSIH#5B`u_QA;FTS8CKPxr4grV); bhVvClh72ige-o!f>L@us_x}d~4%bF>AD~SQ literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/43/52f2dfe637a766c7fe558cc85b961860efd50c b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/43/52f2dfe637a766c7fe558cc85b961860efd50c new file mode 100644 index 0000000000000000000000000000000000000000..6140b56e45f56e7098b36bec26120d53339670f7 GIT binary patch literal 127 zcmV-_0D%8^0ZYosPf{>4Fk?t7%Fk6u$x6&i&(}*yQpn6L$S*2U$jwhl%_-*MO3q0v zE>>{VfbjKvLBg6=T%38OIXUrZnW;G`3bs(idY*YDsp+XjZXi(&kOJF~qS91NpyJf> h_`Lj*c;Ym5HDfR|FfcPQQHYPv%*!l^kJl@xWOz3B(d zXRX2%krtd}m%UX!-NXP06mm1uixNvR^Ye-s)~DpW-~J_Px0;Z-W7tK5%~kE80#I{u z^HWlDz$Q)VpJ{Phz{_H`Tcq-iSMq0`Z#`B4RaBB%Tmn{8^OX6}-RZk3BJ14FlR_B%Fk6u$x6&i&(}*yQpn6L$S*2U$jwhl%_-*MO3q0v zE>>{VfbjKvLBg6=T%38OIXUrZnW;G`3bs(idY*YDsp+XjZXi(&kOJF~qS91NE>7jV g)bjYe{E~R$bh#zw6eF|&%}GqkNhQ`Y0K8*M&i)KNqyPW_ literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 new file mode 100644 index 0000000000000000000000000000000000000000..adf64119a33d7621aeeaa505d30adb58afaa5559 GIT binary patch literal 15 Wcmb`Ö4PBŠ�’M»•ͶiA©�ºgì4‡l± kÀ�S˜Œn¸2\ XÃ,úÈ;z#<¯ª“XÅÍŽ1¸ŽÅ É"FèൈyQñ„1õzšx \JÙôŽ\rÚóM]\o !Lù�\áÏý¯Ðk½­Vx(u{Ò#v\ó™õ<‹JøÞÓÅ{m<ö§Løg+Z·ü-ž(á€ó’”Ϻ—ù‚_]3t­ý ¡¢o� \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/63/973d01988ba594743a8046c9c88c2aa527d307 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/63/973d01988ba594743a8046c9c88c2aa527d307 new file mode 100644 index 0000000000000000000000000000000000000000..3f771d5c1e30263214cd2a30914b52def2ef7c86 GIT binary patch literal 42 zcmV+_0M-9^0ZYosPf{?lV9?Sls7&UHj|Y;8$r-8f@%mg^#f3SUC8@?-0MJ1TW5lu) A#Q*>R literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/47b0f2a9845fa268ad4a19967c706e5d7be38b b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/47b0f2a9845fa268ad4a19967c706e5d7be38b new file mode 100644 index 0000000000000000000000000000000000000000..621f4fc1cb882e93252ee56b37a204041d5c4f7a GIT binary patch literal 296 zcmV+@0oVR`0bP*6PQx$|L^U8Q_FU`an}IOGdHqO3|KuqZ~q*G}>)p z3=g6+>lAkmUe2ra)l^=@%`wX$jG&3MAl*rF(7@{=#>G1KDx!)Z{!*$f(Cjs-{oW#-pB{Y$&vjaJR45ohv^!AsrC(4Ly?}(o|(-6 literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/5de5db8bc5e1ed29b3cb7ece62b5e7c8db06ee b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/73/5de5db8bc5e1ed29b3cb7ece62b5e7c8db06ee new file mode 100644 index 0000000000000000000000000000000000000000..66ccc09794ebf5efe30fa53a069a0084dc53b13f GIT binary patch literal 391 zcmV;20eJp+0gX~!OT#b}^*O)dGK8*B6Xt`1f)64N2R?~DiO#f5w~QvYB&i?&-kYq2 zF;MJN8qPiE+;dWOSiy36bvB#LI&Fh;o1lEy^bYr`4)FZ=0Jmscy&aqk8ZBc_I|c89 z>v|aoZv8uS+6Qnr&}1C&5D-4J`t%%D=)j;;plyrJBns#|CA|W#RLOw8T?oA|g=nz$ zyxB{;#ZjNvXoRw2!50e=u-CO05iLmH3wHM<4Uzehtp;01dk5Xby5MlrG$1W#)1wO| zK6IR}2iNeD+>IS3L^O~N-0Pr{dS0+s_5=3-1~NL0#8UtO literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/7c/e503c2dd97ba78597f6ff6e4393132753573f6 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/7c/e503c2dd97ba78597f6ff6e4393132753573f6 new file mode 100644 index 0000000000000000000000000000000000000000..250bef6ac737f97163f7f541ed98f1f4581b0f67 GIT binary patch literal 72 zcmV-O0Jr~m0ZYosPf{>5U`Q*<&s9jtO3X{o*DFaaE>XzLEyyn_Q3wIDofC^wxww=S eoQqNuOHvgo^Gk~qKx&E=GE$3D^|$~d*cUrI-yGBc literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/86/deb0cf782231006446fd6194592c2243e74ffe b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/86/deb0cf782231006446fd6194592c2243e74ffe new file mode 100644 index 0000000..635c9d7 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/86/deb0cf782231006446fd6194592c2243e74ffe @@ -0,0 +1 @@ +x+)JMU04±`040031Qˆ�ÏÌË,‰�×+¨dx6÷ÑìM¯9{wk®+�ºqèIOðD¨²âÔ’’̼ôb�²)ûw—Êo literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/8e/2c3931324179d354f7f87a25e642778ed734f9 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/8e/2c3931324179d354f7f87a25e642778ed734f9 new file mode 100644 index 0000000000000000000000000000000000000000..e6aa0ad0650522bd3089433c0ba0d687ffcfbbfd GIT binary patch literal 256 zcmV+b0ssDZ0bP&5YQr!PM0?g(Ec74;9AlYKLcoVYN$H_qP>PVFwNa2)LQ-1#_l>M3 zX}ibS**CL;bpvd~!`(eRBVkYpH4I;0U@_Y}c(=i!F5BuG=s+1~-FV zY>ghk%-)3rvzg8e<0#fJJB>Cn#tv4+2(On_bu%?rakXO%&ZE&IX{3X}2tB+lVqR1{ zVN6na&uidq+X`vOB%>@})r;%B5S-6%Y$gJln zD&eOjmn5C6m18FSvn^U*{%&3<;e??iX&lwbre6GXEm!~_Fk<*Xc`@vjjd%;czV;1O Gzj@_r)Odpc literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/91/ea44a218fbd2f408430959283f0419c921093e b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/91/ea44a218fbd2f408430959283f0419c921093e new file mode 100644 index 0000000000000000000000000000000000000000..263fc8c87e325bcaa3c19492252655b82f498d2d GIT binary patch literal 77 zcmV-T0J8sh0ZYosPf{>5W=Jc_&s9jtO3X{o*DKD*FDgkcEh$#W%q;*i6^c^xQc{b! jxRe!~i&7IyQWYxmON$iBGE>Wo6*5wbQuVk1gVGqx_PZe6 literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/92/8f9938db104a389b465923b8ea1fcce7b5c678 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/92/8f9938db104a389b465923b8ea1fcce7b5c678 new file mode 100644 index 0000000000000000000000000000000000000000..b6aaa4070d37c8fc9187cd3439f1f5212e4a2886 GIT binary patch literal 124 zcmV-?0E7Q{0ZYosPf{>4Fl9(9%Fk6u$x6&i&(}*yQpn6L$S*2U$jwhl%_-*MO3q0v zE>>{VfbjKvLBg6=T%38OIXUrZnW;G`3bs(idY*YDsp+XjZXi(&kOJF~qS91NpyJf> e_`Lj*c;Ym z>UR9!dsY`Nsd4O1ctFygJ@@Zi#xWa{H?5!F{&0ABsCDK+I%PzFlr)_RGGUxZ5Ymqz z1__a$&?yfjWvQQWHiuA>>S<_N7g9hXL}YwV^r#Tk2%?0hM96^4>ZVR|fx=0pt7WuW z#xKZzg}M^PfzTAyCWRKlQX*#*4WTidpZ_a}Y05#$mFhNd;1)Nya#;5Sn&GE^``3 zBn#wBpm%~spmf!tLt_@|fQk#eZ>Vd=oYD07(sV7qV-L@WVHhV`{Yl=fuSJxnK?27$ z+t=U0SSWGFzOMr4`zI$SnlkA3oQ8`=krfib5@MDmkjhOs8YE9ePGvBTF=Ch*jB%8Q zD)Y$h0+46sVa8UHH6zGkcCS=4!x@AN6@E+!O0wFcq3wMnx8`tQ54sm*0gx5Z5fE~a z_ppUV3(G zZ+AL93)5?u;xojIrS-f*jz{+jj;tBoxwZt2Nh-mRwDOhc9bZ?e}h-xkp?^RSmUSx3wW5on8f5H7IK8h>1I zY!ObT&?a`cF*`%Y@%+)S*LDV1s(_wu_D0TQffeIf{p+6TSsS$eQzW*)?WNiNU=2F@ z#TvpAk}Sr-V2sfuNTa%M8|4V_DsqjVLJGD$7e##jQX;-M!}?I|P@Stv+oCwvp6v`2 zVPiCtCrNW+op={GvKijQ)*!0*L@D5f<3+y z;1~%6;OjGo#?CxFiYk5_r5)2V)fiO3D>JQQD-H5k?xbF~23>n#;aQa&e-bRfuLb#Q z9IjuIdvO<6fqBp#3cIfZAy$k>Y9pY?Th6}!<$}syBdg>!DtQP-92O(*y?<@G?yWQI z_%~+HMjxHwqm?x<`&&M3CWGoVwQzr9tT7V6O{u0wF2SVfjw%Wpd!H5qkC8+p-N?Y`xIat6iW$ZKN_jc^ULTj#0*%MC*v^jfcX54=xn zx>~G?v0UuUf*iM9_l*1&ECV;>G?Qn7He)a}FfcPQQ7|wtFpSU4%Ph%E%+V{TWYE5ETwZP2{onr- zAJ`Ö4PBŠ�’M»•ͶiA©�ºgì4‡l± kÀ�S˜Œn¸2\ XÃ,úÈ;z#<¯ª“XÅÍŽ1¸ŽÅ É"FèൈyQñ„1õzšx \JÙôŽ\rÚóM]\o !Lù�\áÏý¯Ðk½­Vx(u{Ò#v\ó™õ<‹JøÞÓÅ{m<ö§Løg+Z·ü-ž(á€ó’”Ϻ—ù‚_]3t­ý ¢ðo‚ \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/be/2fae887ee7ecd2d1e6371af1a865c17414bde9 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/be/2fae887ee7ecd2d1e6371af1a865c17414bde9 new file mode 100644 index 0000000..5985521 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/be/2fae887ee7ecd2d1e6371af1a865c17414bde9 @@ -0,0 +1 @@ +x¥ŽAn1 EYçÞ£¢1N2Œ„*Ü¡kÇvÚˆ™ JÓrýâ]¾÷¥§/uYJ‡c ]of@¢j^#“ž‚¤ƒ÷qœÐ&’ñdÂB¦ÁݹÙÚa[MrDœèD(a¦ØÛ8L)'�Èž}bÇ?ý«6¸òoÑ·�šZ•œõ‰‡Ç /Ÿ —ù uyߺ ½#ì·Ùíh·$ÜÕfë¹Ì¼*”õÛZ‡Õî7zRY \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/e0/00041da0b7dc84cb17be523882c118641b72b5 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/e0/00041da0b7dc84cb17be523882c118641b72b5 new file mode 100644 index 0000000..0363066 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/e0/00041da0b7dc84cb17be523882c118641b72b5 @@ -0,0 +1,2 @@ +xm�AkÃ0 …wö¯>µÐÅt ƒíJÇÖÚ±câÄJêb[ÁVÛíß/I[èa'!žô¾'•ŽJx|xº“RŠïÍb …Ú6PSgcÌçm¤=V —š ±dÀŸ–&àÂyY;§K‡ hðdïÑÁQG;HA{4Pºm�­4[ +EÑù½uDOÁ†î(tæ6AmN !Šs›ž•2T¥Ììuhèš©"¯0¨i6�ª�˜”ÁÖѯÇÀꔫD¦°¾¥È@Iˆ:’‡³KVuð¬ƒË@ƒœ÷}~UJ†£�²„l°ÖÇ#9{]-Öùf¾Ý.W‹Mþ¹ž}}Ìåäð?ƒMîm‡Ó®íM؆&ɱ7 x�ÿø£±ø°è™ž \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/e4/9014e99d282c96e97490f64f13dba56637acc3 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/e4/9014e99d282c96e97490f64f13dba56637acc3 new file mode 100644 index 0000000000000000000000000000000000000000..2b34cf3674922647d64329da6200fb7cb85269e2 GIT binary patch literal 240 zcmV5HDfR|FfcPQQHYPv%*!l^kJl@xWOz3B(d zXRX2%krtd}m%UX!-NXP06mm1uixNvR^Ye-s1j<6D%k=hKS;V=)%+`(N&%EbXra;Zf z%}+_q0h{C;^y&UH^W|yB|AqFPh@K{q@ct?fR8dK4aS2#W%~R$>cc<^Fh^){5_QcZA qsMNIh8&pkMW@S;s4_7GiNX~FfcPQQP4}zEXhpI%P&f0NSKmlGK#=+|2Z%#FEVXy!e8m{H)aE5{9;W b8_riK88W1}{Y{(_siWll-2Wc{9MwjCr)gMv literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/f7/9f238852ec7cd7b9a3cc7f6b9b5324d380ae8b b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/f7/9f238852ec7cd7b9a3cc7f6b9b5324d380ae8b new file mode 100644 index 0000000000000000000000000000000000000000..2b45f0b3053eba6175d3fb96984611427d7964f5 GIT binary patch literal 111 zcmV-#0FeK90ZYosPf{>6HDpLD%Fk6u$x6&i&(}*yQpn6L$S*2U$jwhl%_-*MO3q0v zE>>{VfbjKvLBg6=T%38OIXUrZnW;G`3bs(idY*YDsp+XjZXi(&kOJF~qS91NpyJf> Rco07^DJPX!O#o1?H|KNVG!Xy* literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/fc/04070e8336f17e3b2402586653623e6bb51f67 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/fc/04070e8336f17e3b2402586653623e6bb51f67 new file mode 100644 index 0000000000000000000000000000000000000000..a0339be7c120f5ad7bb6d3595d3826bf03fb9027 GIT binary patch literal 88 zcmV-e0H^oeKbS6(DiPJS2($ literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master b/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master new file mode 100644 index 0000000..953a67e --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master @@ -0,0 +1 @@ +be2fae887ee7ecd2d1e6371af1a865c17414bde9 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/manage.py b/tests/test_project_fixtures/test_deleted_migration_project/manage.py new file mode 100644 index 0000000..3a629de --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_deleted_migration_project.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/__init__.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/admin.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/apps.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/apps.py new file mode 100644 index 0000000..fc04070 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TestAppConfig(AppConfig): + name = 'test_app' diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0001_initial.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0001_initial.py new file mode 100644 index 0000000..2bdf337 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0001_initial.py @@ -0,0 +1,21 @@ +# Generated by Django 2.0.1 on 2018-01-18 22:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='A', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('null_field', models.IntegerField(null=True)), + ], + ), + ] diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py new file mode 100644 index 0000000..b30169e --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.1 on 2018-01-18 22:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('test_app', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='a', + name='new_nullable_field', + field=models.IntegerField(null=True), + ), + ] diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/__init__.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py new file mode 100644 index 0000000..928f993 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py @@ -0,0 +1,6 @@ +from django.db import models + +class A(models.Model): + null_field = models.IntegerField(null=True) + new_not_null_field = models.IntegerField(null=False) + new_nullable_field = models.IntegerField(null=True) diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/tests.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/views.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/__init__.py b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/settings.py b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/settings.py new file mode 100644 index 0000000..94bfbb7 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/settings.py @@ -0,0 +1,120 @@ +""" +Django settings for test_deleted_migration_project project. + +Generated by 'django-admin startproject' using Django 1.11.6. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'gtb+mohs%gf0+#fr89vw7e&#edmv=q8!iv+n&j_soawk$tkj3^' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'test_app' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'test_deleted_migration_project.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'test_deleted_migration_project.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django_fake_database_backends.backends.mysql', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/urls.py b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/urls.py new file mode 100644 index 0000000..735de5d --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/urls.py @@ -0,0 +1,21 @@ +"""linter_test_project URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/wsgi.py b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/wsgi.py new file mode 100644 index 0000000..e000041 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_deleted_migration_project/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for linter_test_project project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_deleted_migration_project.settings") + +application = get_wsgi_application() From 698e658faabec08d380c42ef723c9d4766f95643 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 20 Jan 2018 15:50:45 +0100 Subject: [PATCH 08/11] Fix test : do not consider deleted migrations * Change way to detect deleted migrations (diff-filter of 'git diff' command) --- django_migration_linter/migration_linter.py | 9 +++++---- tests/functional/test_cmd_line_call.py | 15 +++++++++++++++ .../git/COMMIT_EDITMSG | 15 +++++++++++++++ .../test_deleted_migration_project/git/index | Bin 1581 -> 1581 bytes .../git/logs/HEAD | 1 + .../git/logs/refs/heads/master | 1 + .../20/6a76068032bb321ca63f561a230675d2645182 | Bin 0 -> 136 bytes .../39/0459eae1e9c3eecaac732d51867c8b8ed5102f | Bin 0 -> 239 bytes .../4b/330bb1c7154afb23f170218d170dae079c437f | 2 ++ .../4b/dc4ba9e7695893423be1b54f3101d6ccbd11c7 | Bin 0 -> 183 bytes .../87/39ba2b3bc1f8efddd5806ec429405150505b81 | Bin 0 -> 173 bytes .../fb/cc4dab70fb36389f806bb72fd5056f5034f572 | Bin 0 -> 216 bytes .../git/refs/heads/master | 2 +- .../migrations/0003_new_nullable_field.py | 13 +++++-------- .../test_app/models.py | 2 +- 15 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/20/6a76068032bb321ca63f561a230675d2645182 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/39/0459eae1e9c3eecaac732d51867c8b8ed5102f create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/330bb1c7154afb23f170218d170dae079c437f create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/dc4ba9e7695893423be1b54f3101d6ccbd11c7 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/87/39ba2b3bc1f8efddd5806ec429405150505b81 create mode 100644 tests/test_project_fixtures/test_deleted_migration_project/git/objects/fb/cc4dab70fb36389f806bb72fd5056f5034f572 diff --git a/django_migration_linter/migration_linter.py b/django_migration_linter/migration_linter.py index 7ecbf98..00a44eb 100644 --- a/django_migration_linter/migration_linter.py +++ b/django_migration_linter/migration_linter.py @@ -152,8 +152,10 @@ class MigrationLinter(object): def _gather_migrations_git(self, git_commit_id): migrations = [] # Get changes since specified commit - git_diff_command = 'cd {0} && git diff --name-status {1}'.format( - self.django_path, git_commit_id) + git_diff_command = ( + 'cd {0} && ' + 'git diff --name-only --diff-filter=A {1}').format( + self.django_path, git_commit_id) log.info('Executing {0}'.format(git_diff_command)) diff_process = Popen( git_diff_command, shell=True, stdout=PIPE, stderr=PIPE) @@ -161,10 +163,9 @@ class MigrationLinter(object): utils.clean_bytes_to_str, diff_process.stdout.readlines()): # Only gather lines that include added migrations if re.search( - '^A.*\/{0}\/.*\.py'.format(self.MIGRATION_FOLDER_NAME), + '\/{0}\/.*\.py'.format(self.MIGRATION_FOLDER_NAME), line) and \ '__init__' not in line: - line = line.split()[-1] # Remove the status letter app_name, migration_name = self._split_migration_path(line) migrations.append((app_name, migration_name)) diff_process.wait() diff --git a/tests/functional/test_cmd_line_call.py b/tests/functional/test_cmd_line_call.py index ac62575..a3afd33 100644 --- a/tests/functional/test_cmd_line_call.py +++ b/tests/functional/test_cmd_line_call.py @@ -116,6 +116,21 @@ class CallLinterFromCommandLineTest(unittest.TestCase): self.assertTrue(lines[2].endswith('IGNORE')) def test_call_linter_cmd_line_git_id(self): + cmd = '{0} {1} d7125d5f4f0cc9623f670a66c54f131acc50032d'.format( + self.linter_exec, + fixtures.MULTI_COMMIT_PROJECT) + fixtures.prepare_git_project(fixtures.MULTI_COMMIT_PROJECT) + + process = Popen( + cmd, shell=True, stdout=PIPE, stderr=PIPE) + process.wait() + self.assertEqual(process.returncode, 0) + lines = list(map(utils.clean_bytes_to_str, process.stdout.readlines())) + self.assertEqual(len(lines), 3) + self.assertTrue(lines[0].endswith('OK')) + self.assertTrue(lines[1].startswith('*** Summary')) + + def test_call_linter_with_deleted_migrations(self): cmd = '{0} {1} 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba'.format( self.linter_exec, fixtures.DELETED_MIGRATION_PROJECT) diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG b/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG index 974dd96..e513fa5 100644 --- a/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/COMMIT_EDITMSG @@ -1 +1,16 @@ Delete file and insert new + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# Date: Thu Jan 18 23:27:37 2018 +0100 +# +# On branch master +# Changes to be committed: +# deleted: test_app/migrations/0002_new_not_null_field.py +# new file: test_app/migrations/0003_new_nullable_field.py +# modified: test_app/models.py +# +# Untracked files: +# git/ +# diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/index b/tests/test_project_fixtures/test_deleted_migration_project/git/index index b3e362d0e1ceeeda1718673cb37a52dd4f808748..a41e52a9d31bcca1caae10b6449e970defe30e4a 100644 GIT binary patch delta 626 zcmZ3>vzAB2#WTp6fq{Vui20+E1KW(vW!}JOpcoGWAUQdaf>H6SSv4UyXH zG_k}GEERj111trkp;8GG_c(&3YC?a2rGPY4DrK?=BgDiOfd^nYAPtqvn4E%BE_d=4 z#z5=jkgwLvzAB2#WTp6fq{Vui20)e|7NIL7e0W|KrtQ$_LkC#Dwg7jvRn9O2waGQ(h#Zk znG;J4#eur?zZdKP=>pMUDZx(piF+KeOLc6VEW&7sU9MAVatcr`QEq}|!fJ~sC=E4o z$>c4Jf!2xgo+?`>y@*Pbw_@%(X8@Jk!@$tE1jvR0#+uEHna^+jlRw3?*2umPP-$f1yRTZE 1516314144 +0100 commit (initial): Project init 0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba David-Wobrock 1516314322 +0100 commit: Add backward incompatible migration 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba be2fae887ee7ecd2d1e6371af1a865c17414bde9 David-Wobrock 1516314457 +0100 commit: Delete file and insert new +be2fae887ee7ecd2d1e6371af1a865c17414bde9 4bdc4ba9e7695893423be1b54f3101d6ccbd11c7 David-Wobrock 1516459290 +0100 commit (amend): Delete file and insert new diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master index 236e554..5377828 100644 --- a/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/logs/refs/heads/master @@ -1,3 +1,4 @@ 0000000000000000000000000000000000000000 0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e David-Wobrock 1516314144 +0100 commit (initial): Project init 0395cbee60f2ea1b97f42ebdd43991c8f5d8d76e 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba David-Wobrock 1516314322 +0100 commit: Add backward incompatible migration 154ecf6119325cc3b1f3f5a4e709bfbd61a4a4ba be2fae887ee7ecd2d1e6371af1a865c17414bde9 David-Wobrock 1516314457 +0100 commit: Delete file and insert new +be2fae887ee7ecd2d1e6371af1a865c17414bde9 4bdc4ba9e7695893423be1b54f3101d6ccbd11c7 David-Wobrock 1516459290 +0100 commit (amend): Delete file and insert new diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/20/6a76068032bb321ca63f561a230675d2645182 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/20/6a76068032bb321ca63f561a230675d2645182 new file mode 100644 index 0000000000000000000000000000000000000000..40a0fd72288df09ba30d2e972055fa35f666b706 GIT binary patch literal 136 zcmV;30C)d*0V^p=O;s>7He)a}FfcPQQ7|wtFpSU4%Ph%E%+V{TWYE5ETwZP2{onr- zAJnWZ!?Se4cXiEud?O` qn0zgQ>WT-O9v=@<_H6E>*_$q2bN24mTvr}-5HDfR|FfcPQQHYPv%*!l^kJl@xWOz3B(d zXRX2%krtd}m%UX!-NXP06mm1uixNvR^Ye-s6tc?L8jN-u$t<%ElTv0Yy_6Ez1T`l& zKP5E>Y?8Mz_r~L*UcZ$;7AW?L^R8o`<6I9_RFYa;0#;M=l=;xz>ANZ->+`=ou{1O) pH7))IRa2IkS`Jn-@s-OWiQkvLa5!^DYS^<#o>b(t0{|*MV-k}Ha3}x( literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/330bb1c7154afb23f170218d170dae079c437f b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/330bb1c7154afb23f170218d170dae079c437f new file mode 100644 index 0000000..d261e11 --- /dev/null +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/330bb1c7154afb23f170218d170dae079c437f @@ -0,0 +1,2 @@ +x�ޱ +Â0E]íW¼± RAÈ …‚ƒ›{Hš×´ò’H’¢ŸocÄÉñ^Îá^E^A]ïW}ðôU:ã™V0Ú› ¬×H±(:’1±\2;çº:k7‰~DÒÀß0;¹„C›Û2ü&¬fïÂù$þ“ZIñcuƒ /M*B‘0¦ßÑf&–E+‚Й4ðÝv_ž<4Si \ No newline at end of file diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/dc4ba9e7695893423be1b54f3101d6ccbd11c7 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/4b/dc4ba9e7695893423be1b54f3101d6ccbd11c7 new file mode 100644 index 0000000000000000000000000000000000000000..4b414329e06d85a1b4a1a695c0c20df9ba984357 GIT binary patch literal 183 zcmV;o07(CM0hNwHPQ)+_MOo(*-XlhF;plPjX(|(9^e&|21&c3% zNoO0SNS=_1N!ak`cxxT5{8jVQOOxKxJDl?mp67GiNX~FfcPQQP4}zEXhpI%P&f0NS>~6S+o4xGho5 literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/objects/fb/cc4dab70fb36389f806bb72fd5056f5034f572 b/tests/test_project_fixtures/test_deleted_migration_project/git/objects/fb/cc4dab70fb36389f806bb72fd5056f5034f572 new file mode 100644 index 0000000000000000000000000000000000000000..5807b0bd305a2bcc4a4426bea3387455ffffbe82 GIT binary patch literal 216 zcmV;}04M)=0d-G1Yr`-Q?yO&Nn`|&fCD5Uup%l7x>lT7ITNg(`FC>NZ=Qonmq%HKO z}i)ylDMq$m;HP zY=l}+d2}Q>^5NHQMLnI>e88mq$y%H&sn%v+z5WOqCSCh^e7$JaK!=~ol3&U}Zo~l9 SM}DLe_4l~zx?^7<7;y?WPir~= literal 0 HcmV?d00001 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master b/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master index 953a67e..c422dbc 100644 --- a/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master +++ b/tests/test_project_fixtures/test_deleted_migration_project/git/refs/heads/master @@ -1 +1 @@ -be2fae887ee7ecd2d1e6371af1a865c17414bde9 +4bdc4ba9e7695893423be1b54f3101d6ccbd11c7 diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py index b30169e..fbcc4da 100644 --- a/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/migrations/0003_new_nullable_field.py @@ -1,18 +1,15 @@ -# Generated by Django 2.0.1 on 2018-01-18 22:26 - -from django.db import migrations, models +from django.db import migrations +from django.db import models class Migration(migrations.Migration): - dependencies = [ - ('test_app', '0001_initial'), - ] + dependencies = [('test_app', '0001_initial'),] operations = [ migrations.AddField( model_name='a', - name='new_nullable_field', - field=models.IntegerField(null=True), + name='new_char_nullable_test_field', + field=models.CharField(max_length=30, null=True), ), ] diff --git a/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py b/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py index 928f993..4b330bb 100644 --- a/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py +++ b/tests/test_project_fixtures/test_deleted_migration_project/test_app/models.py @@ -3,4 +3,4 @@ from django.db import models class A(models.Model): null_field = models.IntegerField(null=True) new_not_null_field = models.IntegerField(null=False) - new_nullable_field = models.IntegerField(null=True) + new_char_nullable_test_field = models.CharField(max_length=30, null=True) From 3037585cc24e896983ae8ce4b7efe16cebb2ccf7 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 20 Jan 2018 15:59:38 +0100 Subject: [PATCH 09/11] Fix #9 - add information message when altering columns - may be backward compatible --- django_migration_linter/sql_analyser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_migration_linter/sql_analyser.py b/django_migration_linter/sql_analyser.py index 7699aeb..9b41008 100644 --- a/django_migration_linter/sql_analyser.py +++ b/django_migration_linter/sql_analyser.py @@ -53,7 +53,7 @@ migration_tests = ( }, { 'code': 'ALTER_COLUMN', 'fn': lambda sql, **kw: re.search('ALTER TABLE .* MODIFY', sql), - 'err_msg': 'ALTERING columns' + 'err_msg': 'ALTERING columns (Could be backward compatible. You may ignore this migration.)' }, { 'code': '', 'fn': has_default, From 07de522fced8efba1366e4bc2aa20e48e145f1af Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 20 Jan 2018 16:02:58 +0100 Subject: [PATCH 10/11] Remove git samples --- .../git/hooks/applypatch-msg.sample | 15 -- .../git/hooks/commit-msg.sample | 24 --- .../git/hooks/post-update.sample | 8 - .../git/hooks/pre-applypatch.sample | 14 -- .../git/hooks/pre-commit.sample | 49 ----- .../git/hooks/pre-push.sample | 54 ------ .../git/hooks/pre-rebase.sample | 169 ------------------ .../git/hooks/prepare-commit-msg.sample | 36 ---- .../git/hooks/update.sample | 128 ------------- 9 files changed, 497 deletions(-) delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/applypatch-msg.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/commit-msg.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/post-update.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-applypatch.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-commit.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-push.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-rebase.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/prepare-commit-msg.sample delete mode 100644 tests/test_project_fixtures/test_project_multi_commit/git/hooks/update.sample diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/applypatch-msg.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/applypatch-msg.sample deleted file mode 100644 index 8b2a2fe..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -test -x "$GIT_DIR/hooks/commit-msg" && - exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} -: diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/commit-msg.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/commit-msg.sample deleted file mode 100644 index b58d118..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/post-update.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/post-update.sample deleted file mode 100644 index ec17ec1..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-applypatch.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-applypatch.sample deleted file mode 100644 index b1f187c..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -test -x "$GIT_DIR/hooks/pre-commit" && - exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} -: diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-commit.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-commit.sample deleted file mode 100644 index 68d62d5..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-push.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-push.sample deleted file mode 100644 index 1f3bceb..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-push.sample +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -z40=0000000000000000000000000000000000000000 - -IFS=' ' -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Check for WIP commit - commit=`git rev-list -n 1 --grep '^WIP' "$range"` - if [ -n "$commit" ] - then - echo "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-rebase.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-rebase.sample deleted file mode 100644 index 33730ca..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up-to-date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -<<\DOC_END - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". - -DOC_END diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/prepare-commit-msg.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/prepare-commit-msg.sample deleted file mode 100644 index f093a02..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first comments out the -# "Conflicts:" part of a merge commit. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -case "$2,$3" in - merge,) - /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; - -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$1" ;; - - *) ;; -esac - -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/update.sample b/tests/test_project_fixtures/test_project_multi_commit/git/hooks/update.sample deleted file mode 100644 index d847583..0000000 --- a/tests/test_project_fixtures/test_project_multi_commit/git/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to blocks unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 From eebbcc4cc034f392870575ca3226c0b73fedf2f8 Mon Sep 17 00:00:00 2001 From: David-Wobrock Date: Sat, 20 Jan 2018 16:10:41 +0100 Subject: [PATCH 11/11] Fix PEP8 requirement --- django_migration_linter/sql_analyser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/django_migration_linter/sql_analyser.py b/django_migration_linter/sql_analyser.py index 9b41008..636be21 100644 --- a/django_migration_linter/sql_analyser.py +++ b/django_migration_linter/sql_analyser.py @@ -53,7 +53,8 @@ migration_tests = ( }, { 'code': 'ALTER_COLUMN', 'fn': lambda sql, **kw: re.search('ALTER TABLE .* MODIFY', sql), - 'err_msg': 'ALTERING columns (Could be backward compatible. You may ignore this migration.)' + 'err_msg': ('ALTERING columns (Could be backward compatible. ' + 'You may ignore this migration.)') }, { 'code': '', 'fn': has_default,