diff --git a/annexremote/annexremote.py b/annexremote/annexremote.py index e3013d8..d1a56ea 100644 --- a/annexremote/annexremote.py +++ b/annexremote/annexremote.py @@ -388,6 +388,10 @@ class ExportRemote(SpecialRemote): Note that the user is not required to provided all the settings listed here. """ + def __init__(self, annex, force_version1=False): + self.force_version1 = force_version1 + super().__init__(annex) + def exportsupported(self): return True @@ -545,10 +549,16 @@ class Protocol(object): def __init__(self, remote): self.remote = remote - self.version = "VERSION 1" self.exporting = False self.extensions = list() + @property + def version(self): + if self.remote.exportsupported() and not self.remote.force_version1: + return "VERSION 2" + else: + return "VERSION 1" + def command(self, line): line = line.strip() parts = line.split(" ", 1) @@ -734,6 +744,8 @@ def do_EXPORTSUPPORTED(self): return "EXPORTSUPPORTED-FAILURE" def do_EXPORT(self, name): + if self.exporting: + raise UnexpectedMessage("Unexpected EXPORT") self.exporting = name def do_TRANSFEREXPORT(self, param): diff --git a/examples/git-annex-remote-directory b/examples/git-annex-remote-directory index c423029..f9a65b8 100755 --- a/examples/git-annex-remote-directory +++ b/examples/git-annex-remote-directory @@ -133,7 +133,6 @@ class DirectoryRemote(ExportRemote): def main(): - # Redirect output to stderr to avoid messing up the protocol output = sys.stdout sys.stdout = sys.stderr diff --git a/tests/test_GitAnnexRequestMessages.py b/tests/test_GitAnnexRequestMessages.py index cce8902..e61eebd 100644 --- a/tests/test_GitAnnexRequestMessages.py +++ b/tests/test_GitAnnexRequestMessages.py @@ -10,7 +10,7 @@ UnsupportedReqeust = utils.annexremote.UnsupportedRequest -class TestGitAnnexRequestMessages(utils.GitAnnexTestCase): +class TestGitAnnexRequestMessages(utils.ExportTestCase): def test_InitremoteSuccess(self): self.annex.Listen(io.StringIO("INITREMOTE")) self.remote.initremote.call_count == 1 @@ -363,7 +363,7 @@ def test_Error(self): self.remote.error.assert_called_once_with("ErrorMsg") -class TestGitAnnexRequestMessagesExporttree(utils.GitAnnexTestCase): +class TestGitAnnexRequestMessagesExporttree(utils.ExportTestCase): def test_ExportsupportedSuccess(self): self.annex.Listen(io.StringIO("EXPORTSUPPORTED")) self.remote.exportsupported.call_count == 1 @@ -387,6 +387,11 @@ def test_Export_MissingName(self): r"ERROR (Protocol\.|)do_EXPORT\(\) missing 1 required positional argument: 'name'", ) + def test_Export_DoubleExport(self): + with self.assertRaises(SystemExit): + self.annex.Listen(io.StringIO("EXPORT Name1\nEXPORT Name2")) + self.assertEqual(utils.last_buffer_line(self.output), "ERROR Unexpected EXPORT") + def test_Export_SpaceInName(self): # testing this only with TRANSFEREXPORT self.annex.Listen( @@ -675,7 +680,7 @@ def prepare(self): self.logger.warning("test\nthis is a new line") -class TestLogging(utils.GitAnnexTestCase): +class TestLogging(utils.ExportTestCase): def setUp(self): super().setUp() self.remote = LoggingRemote(self.annex) diff --git a/tests/test_SpecialRemoteMessages.py b/tests/test_SpecialRemoteMessages.py index 9a893f1..cbe5dc5 100644 --- a/tests/test_SpecialRemoteMessages.py +++ b/tests/test_SpecialRemoteMessages.py @@ -4,7 +4,13 @@ ProtocolError = utils.annexremote.ProtocolError -class TestSpecialRemoteMessages(utils.GitAnnexTestCase): +class TestProtocolVersion2(utils.ExportTestCase): + def TestVersion(self): + self.annex.Listen(self.input) + self.assertEqual(self.output.getvalue(), "VERSION 2\n") + + +class TestSpecialRemoteMessages(utils.FullTestCase): """ * Each protocol line starts with a command, which is followed by the command's parameters (a fixed number per command), each separated by a single space. @@ -451,7 +457,7 @@ def test_Error(self): self._perform_test(function_to_call, function_parameters, expected_output) -class TestSpecialRemoteMessages_Extensions(utils.GitAnnexTestCase): +class TestSpecialRemoteMessages_Extensions(utils.FullTestCase): def _perform_test( self, function_to_call, diff --git a/tests/utils.py b/tests/utils.py index a404a32..704f3f8 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -9,7 +9,7 @@ import annexremote -class GitAnnexTestCase(unittest.TestCase): +class MinimalTestCase(unittest.TestCase): def setUp(self): super().setUp() @@ -17,12 +17,12 @@ def setUp(self): self.input = io.StringIO() self.annex = annexremote.Master(self.output) - self.remote = mock.MagicMock(wraps=DummyRemote(self.annex)) + self.remote = MinimalRemote(self.annex) self.annex.LinkRemote(self.remote) -class MinimalTestCase(unittest.TestCase): +class FullTestCase(unittest.TestCase): def setUp(self): super().setUp() @@ -30,7 +30,20 @@ def setUp(self): self.input = io.StringIO() self.annex = annexremote.Master(self.output) - self.remote = MinimalRemote(self.annex) + self.remote = mock.MagicMock(wraps=FullRemote(self.annex)) + + self.annex.LinkRemote(self.remote) + + +class ExportTestCase(unittest.TestCase): + def setUp(self): + super().setUp() + + self.output = io.StringIO() + self.input = io.StringIO() + + self.annex = annexremote.Master(self.output) + self.remote = mock.MagicMock(wraps=FullExportRemote(self.annex)) self.annex.LinkRemote(self.remote) @@ -77,7 +90,45 @@ def remove(self, key): pass -class DummyRemote(annexremote.ExportRemote): +class FullRemote(annexremote.SpecialRemote): + def initremote(self): + pass + + def prepare(self): + pass + + def transfer_store(self, key, file_): + pass + + def transfer_retrieve(self, key, file_): + pass + + def checkpresent(self, key): + pass + + def remove(self, key): + pass + + def getcost(self): + pass + + def getavailability(self): + pass + + def claimurl(self, url): + pass + + def checkurl(self, url): + pass + + def whereis(self, whereis): + pass + + def error(self, msg): + pass + + +class FullExportRemote(annexremote.ExportRemote): def initremote(self): pass