# Path: alibuild_helpers/sync.py
# class NoRemoteSync:
# class PartialDownloadError(Exception):
# class HttpRemoteSync:
# class RsyncRemoteSync:
# class S3RemoteSync:
# class Boto3RemoteSync:
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, downloaded, size):
#   def __str__(self):
#   def __init__(self, remoteStore, architecture, workdir, insecure):
#   def getRetry(self, url, dest=None, returnResult=False, log=True, session=None):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def _s3_init(self):
#   def _s3_listdir(self, dirname):
#   def _s3_key_exists(self, key):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
# 
# Path: alibuild_helpers/utilities.py
# def resolve_links_path(architecture, package):
#   """Return the path where symlinks for the given package are to be stored.
# 
#   The returned path is relative to the working directory (normally sw/) or the
#   root of the remote store.
#   """
#   return "/".join(("TARS", architecture, package))
# 
# def resolve_store_path(architecture, spec_hash):
#   """Return the path where a tarball with the given hash is to be stored.
# 
#   The returned path is relative to the working directory (normally sw/) or the
#   root of the remote store.
#   """
#   return "/".join(("TARS", architecture, "store", spec_hash[:2], spec_hash))


import sys
import unittest
from io import BytesIO
    from unittest.mock import patch, MagicMock   # In Python 3, mock is built-in
    from mock import patch, MagicMock   # Python 2
from alibuild_helpers import sync
from alibuild_helpers.utilities import resolve_links_path, resolve_store_path
        from botocore.exceptions import ClientError
        self.assertEqual(len(mock_error.call_args_list), 1)
        self.assertEqual(mock_error.call_args_list[0][0][0],
                         "GET %s failed: %s")
        self.assertEqual(mock_error.call_args_list[0][0][1],
                         "https://localhost/test/TARS/%s/store/%s/%s/"
                         "zlib-v1.2.3-2.slc7_x86-64.tar.gz" %
                         (ARCHITECTURE, self.spec["remote_revision_hash"][:2],
                          self.spec["remote_revision_hash"]))
        self.assertIsInstance(mock_error.call_args_list[0][0][2],
                              sync.PartialDownloadError)

        syncer.syncToRemote("zlib", self.spec)
        syncer.syncDistLinksToRemote("/sw/dist")

        mock_debug.reset_mock()
        self.spec["hash"] = self.spec["remote_revision_hash"] = NONEXISTENT_HASH
        self.spec["remote_hashes"] = [NONEXISTENT_HASH]
        syncer.syncToLocal("zlib", self.spec)
        mock_debug.assert_called_with("Nothing fetched for %s (%s)",
                                      "zlib", NONEXISTENT_HASH)

    @patch("alibuild_helpers.sync.execute", new=lambda cmd, printer=None: 0)
    @patch("alibuild_helpers.sync.os")
    def test_sync(self, mock_os):
        # file does not exist locally: force download
        mock_os.path.exists.side_effect = lambda path: False
        mock_os.path.islink.side_effect = lambda path: False
        mock_os.path.isfile.side_effect = lambda path: False

        syncers = [

# Path: alibuild_helpers/sync.py
# class NoRemoteSync:
# class PartialDownloadError(Exception):
# class HttpRemoteSync:
# class RsyncRemoteSync:
# class S3RemoteSync:
# class Boto3RemoteSync:
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, downloaded, size):
#   def __str__(self):
#   def __init__(self, remoteStore, architecture, workdir, insecure):
#   def getRetry(self, url, dest=None, returnResult=False, log=True, session=None):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
#   def __init__(self, remoteStore, writeStore, architecture, workdir):
#   def _s3_init(self):
#   def _s3_listdir(self, dirname):
#   def _s3_key_exists(self, key):
#   def syncToLocal(self, p, spec):
#   def syncToRemote(self, p, spec):
#   def syncDistLinksToRemote(self, link_dir):
# 
# Path: alibuild_helpers/utilities.py
# def resolve_links_path(architecture, package):
#   """Return the path where symlinks for the given package are to be stored.
# 
#   The returned path is relative to the working directory (normally sw/) or the
#   root of the remote store.
#   """
#   return "/".join(("TARS", architecture, package))
# 
# def resolve_store_path(architecture, spec_hash):
#   """Return the path where a tarball with the given hash is to be stored.
# 
#   The returned path is relative to the working directory (normally sw/) or the
#   root of the remote store.
#   """
#   return "/".join(("TARS", architecture, "store", spec_hash[:2], spec_hash))


# Path: tests/test_sync.py
import sys
import unittest
from io import BytesIO
    from unittest.mock import patch, MagicMock   # In Python 3, mock is built-in
    from mock import patch, MagicMock   # Python 2
from alibuild_helpers import sync
from alibuild_helpers.utilities import resolve_links_path, resolve_store_path
        from botocore.exceptions import ClientError

        self.assertEqual(len(mock_error.call_args_list), 1)
        self.assertEqual(mock_error.call_args_list[0][0][0],
                         "GET %s failed: %s")
        self.assertEqual(mock_error.call_args_list[0][0][1],
                         "https://localhost/test/TARS/%s/store/%s/%s/"
                         "zlib-v1.2.3-2.slc7_x86-64.tar.gz" %
                         (ARCHITECTURE, self.spec["remote_revision_hash"][:2],
                          self.spec["remote_revision_hash"]))
        self.assertIsInstance(mock_error.call_args_list[0][0][2],
                              sync.PartialDownloadError)

        syncer.syncToRemote("zlib", self.spec)
        syncer.syncDistLinksToRemote("/sw/dist")

        mock_debug.reset_mock()
        self.spec["hash"] = self.spec["remote_revision_hash"] = NONEXISTENT_HASH
        self.spec["remote_hashes"] = [NONEXISTENT_HASH]
        syncer.syncToLocal("zlib", self.spec)
        mock_debug.assert_called_with("Nothing fetched for %s (%s)",
                                      "zlib", NONEXISTENT_HASH)

    @patch("alibuild_helpers.sync.execute", new=lambda cmd, printer=None: 0)
    @patch("alibuild_helpers.sync.os")
    def test_sync(self, mock_os):
        # file does not exist locally: force download
        mock_os.path.exists.side_effect = lambda path: False
        mock_os.path.islink.side_effect = lambda path: False
        mock_os.path.isfile.side_effect = lambda path: False

        syncers = [

            sync.NoRemoteSync(),