diff --git a/dulwich/reflog.py b/dulwich/reflog.py new file mode 100644 index 00000000..3c15a4c3 --- /dev/null +++ b/dulwich/reflog.py @@ -0,0 +1,42 @@ +# reflog.py -- Parsing and writing reflog files +# Copyright (C) 2015 Jelmer Vernooij and others. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 +# of the License or (at your option) a later version of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +"""Utilities for reading and generating reflogs. +""" + +from dulwich.objects import ( + format_timezone, + ZERO_SHA, + ) + + +def format_reflog_line(old_sha, new_sha, committer, timestamp, timezone, message): + """Generate a single reflog line. + + :param old_sha: Old Commit SHA + :param new_sha: New Commit SHA + :param committer: Committer name and e-mail + :param timestamp: Timestamp + :param timezone: Timezone + :param message: Message + """ + if old_sha is None: + old_sha = ZERO_SHA + return (old_sha + b' ' + new_sha + b' ' + committer + b' ' + + str(timestamp).encode('ascii') + b' ' + + format_timezone(timezone).encode('ascii') + b'\t' + message) diff --git a/dulwich/tests/__init__.py b/dulwich/tests/__init__.py index 862e5a14..1b6a77f2 100644 --- a/dulwich/tests/__init__.py +++ b/dulwich/tests/__init__.py @@ -1,196 +1,197 @@ # __init__.py -- The tests for dulwich # Copyright (C) 2007 James Westby # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2 # of the License or (at your option) any later version of # the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. """Tests for Dulwich.""" import doctest import os import shutil import subprocess import sys import tempfile # If Python itself provides an exception, use that import unittest if sys.version_info < (2, 7): from unittest2 import SkipTest, TestCase as _TestCase, skipIf, expectedFailure else: from unittest import SkipTest, TestCase as _TestCase, skipIf, expectedFailure def get_safe_env(env=None): """Returns the environment "env" (or a copy of "os.environ" by default) modified to avoid side-effects caused by user's ~/.gitconfig""" if env is None: env = os.environ.copy() # On Windows it's not enough to set "HOME" to a non-existing # directory. Git.cmd takes the first existing directory out of # "%HOME%", "%HOMEDRIVE%%HOMEPATH%" and "%USERPROFILE%". for e in 'HOME', 'HOMEPATH', 'USERPROFILE': env[e] = '/nosuchdir' return env class TestCase(_TestCase): def makeSafeEnv(self): """Create environment with homedirectory-related variables stripped. Modifies os.environ for the duration of a test case to avoid side-effects caused by the user's ~/.gitconfig and other files in their home directory. """ old_env = os.environ def restore(): os.environ = old_env self.addCleanup(restore) new_env = dict(os.environ) for e in ['HOME', 'HOMEPATH', 'USERPROFILE']: new_env[e] = '/nosuchdir' os.environ = new_env def setUp(self): super(TestCase, self).setUp() self.makeSafeEnv() class BlackboxTestCase(TestCase): """Blackbox testing.""" # TODO(jelmer): Include more possible binary paths. bin_directories = [os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "bin")), '/usr/bin', '/usr/local/bin'] def bin_path(self, name): """Determine the full path of a binary. :param name: Name of the script :return: Full path """ for d in self.bin_directories: p = os.path.join(d, name) if os.path.isfile(p): return p else: raise SkipTest("Unable to find binary %s" % name) def run_command(self, name, args): """Run a Dulwich command. :param name: Name of the command, as it exists in bin/ :param args: Arguments to the command """ env = dict(os.environ) env["PYTHONPATH"] = os.pathsep.join(sys.path) # Since they don't have any extensions, Windows can't recognize # executablility of the Python files in /bin. Even then, we'd have to # expect the user to set up file associations for .py files. # # Save us from all that headache and call python with the bin script. argv = [sys.executable, self.bin_path(name)] + args return subprocess.Popen(argv, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, env=env) def self_test_suite(): names = [ 'archive', 'blackbox', 'client', 'config', 'diff_tree', 'fastexport', 'file', 'grafts', 'greenthreads', 'hooks', 'index', 'lru_cache', 'objects', 'objectspec', 'object_store', 'missing_obj_finder', 'pack', 'patch', 'porcelain', 'protocol', + 'reflog', 'refs', 'repository', 'server', 'walk', 'web', ] module_names = ['dulwich.tests.test_' + name for name in names] loader = unittest.TestLoader() return loader.loadTestsFromNames(module_names) def tutorial_test_suite(): tutorial = [ 'introduction', 'file-format', 'repo', 'object-store', 'remote', 'conclusion', ] tutorial_files = ["../../docs/tutorial/%s.txt" % name for name in tutorial] def setup(test): test.__old_cwd = os.getcwd() test.__dulwich_tempdir = tempfile.mkdtemp() os.chdir(test.__dulwich_tempdir) def teardown(test): os.chdir(test.__old_cwd) shutil.rmtree(test.__dulwich_tempdir) return doctest.DocFileSuite(setUp=setup, tearDown=teardown, *tutorial_files) def nocompat_test_suite(): result = unittest.TestSuite() result.addTests(self_test_suite()) from dulwich.contrib import test_suite as contrib_test_suite if sys.version_info[0] == 2: result.addTests(tutorial_test_suite()) result.addTests(contrib_test_suite()) return result def compat_test_suite(): result = unittest.TestSuite() from dulwich.tests.compat import test_suite as compat_test_suite result.addTests(compat_test_suite()) return result def test_suite(): result = unittest.TestSuite() result.addTests(self_test_suite()) if sys.version_info[0] == 2 and sys.platform != 'win32': result.addTests(tutorial_test_suite()) from dulwich.tests.compat import test_suite as compat_test_suite result.addTests(compat_test_suite()) from dulwich.contrib import test_suite as contrib_test_suite result.addTests(contrib_test_suite()) return result diff --git a/dulwich/tests/test_reflog.py b/dulwich/tests/test_reflog.py new file mode 100644 index 00000000..4747499c --- /dev/null +++ b/dulwich/tests/test_reflog.py @@ -0,0 +1,55 @@ +# test_reflog.py -- tests for reflog.py +# encoding: utf-8 +# Copyright (C) 2015 Jelmer Vernooij +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 +# of the License or (at your option) any later version of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +"""Tests for dulwich.reflog.""" + + +from dulwich.reflog import format_reflog_line + +from dulwich.tests import ( + TestCase, + ) + + +class FormatReflogLineTests(TestCase): + + def test_valid(self): + self.assertEqual( + b'0000000000000000000000000000000000000000 ' + b'49030649db3dfec5a9bc03e5dde4255a14499f16 Jelmer Vernooij ' + b' 1446552482 +0000 ' + b'clone: from git://jelmer.uk/samba', + format_reflog_line( + b'0000000000000000000000000000000000000000', + b'49030649db3dfec5a9bc03e5dde4255a14499f16', + b'Jelmer Vernooij ', + 1446552482, 0, b'clone: from git://jelmer.uk/samba')) + + self.assertEqual( + b'0000000000000000000000000000000000000000 ' + b'49030649db3dfec5a9bc03e5dde4255a14499f16 Jelmer Vernooij ' + b' 1446552482 +0000 ' + b'clone: from git://jelmer.uk/samba', + format_reflog_line( + None, + b'49030649db3dfec5a9bc03e5dde4255a14499f16', + b'Jelmer Vernooij ', + 1446552482, 0, b'clone: from git://jelmer.uk/samba')) + diff --git a/relicensing-apachev2.txt b/relicensing-apachev2.txt index cdcf4325..07349cdc 100644 --- a/relicensing-apachev2.txt +++ b/relicensing-apachev2.txt @@ -1,25 +1,24 @@ At the moment, Dulwich is licensed under the GNU General Public License, version 2 or later. We'd like to relicense Dulwich under the Apache v2 (or later) license, as the GPL is problematic for many free software Python projects that are under BSD-style licenses. See also https://github.com/jelmer/dulwich/issues/153 For reference, a full copy of the Apachev2 license can be found here: https://www.apache.org/licenses/LICENSE-2.0 New contributions to Dulwich should be dual licensed under the GNU GPLv2 (or later) and the Apachev2 (or later) licenses. Contributions made prior were contributed under the GPLv2 (or later) license alone. Code written by the following contributors has not (yet) been relicensed under dual Apachev2/GPLv2: Artem Tikhomirov -Dmitriy Gary van der Merwé Risto Kankkunen If your name is in this list and you'd be happy to relicense your contribution under dual GPLv2/Apachev2, then please send me an e-mail (jelmer@jelmer.uk) or a pull request on GitHub removing your name from the list above.