Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: moreonion/drupy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.4
Choose a base ref
...
head repository: moreonion/drupy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 19 commits
  • 11 files changed
  • 3 contributors

Commits on May 14, 2017

  1. Copy the full SHA
    e6e5d6e View commit details

Commits on May 23, 2017

  1. Merge pull request #6 from moreonion/reset-once

    Make reset cache it's own target and call it only once.
    torotil authored May 23, 2017
    Copy the full SHA
    06e0a96 View commit details

Commits on May 29, 2017

  1. Copy the full SHA
    a856485 View commit details

Commits on Jul 2, 2017

  1. Copy the full SHA
    7f87258 View commit details
  2. Copy the full SHA
    1bf6583 View commit details
  3. Copy the full SHA
    8390526 View commit details
  4. Merge pull request #7 from moreonion/strip_dir

    Add an optional strip_dir argument to tarballs.
    torotil authored Jul 2, 2017
    Copy the full SHA
    a0ee82c View commit details
  5. Merge pull request #8 from moreonion/yaml

    Use ruamel.yaml instead of PyYAML to get ordered projects.
    torotil authored Jul 2, 2017
    Copy the full SHA
    c42006d View commit details
  6. Prepare 0.5 release.

    torotil committed Jul 2, 2017
    Copy the full SHA
    0623dab View commit details

Commits on Jul 4, 2017

  1. Copy the full SHA
    62c3d73 View commit details
  2. Prepare 0.6 release.

    torotil committed Jul 4, 2017
    Copy the full SHA
    2fbdb07 View commit details

Commits on Sep 19, 2018

  1. Copy the full SHA
    4f4810e View commit details
  2. Merge pull request #10 from m-strasser/master

    'yaml' extra now requires ruamel.yaml <= 0.15.51, fixes issue #9
    torotil authored Sep 19, 2018
    Copy the full SHA
    0930b2c View commit details

Commits on Jan 9, 2019

  1. Copy the full SHA
    ae132f5 View commit details
  2. Add codecov.io

    torotil committed Jan 9, 2019
    Copy the full SHA
    b3618af View commit details
  3. Merge pull request #11 from moreonion/custom-drush

    Add new CLI argument for passing a custom drush executable.
    torotil authored Jan 9, 2019
    Copy the full SHA
    8186e75 View commit details
  4. Prepare 0.7 release.

    torotil committed Jan 9, 2019
    Copy the full SHA
    36ee4ae View commit details

Commits on Jan 17, 2019

  1. Copy the full SHA
    17f0960 View commit details
  2. Prepare 0.7.1 release.

    torotil committed Jan 17, 2019
    Copy the full SHA
    7567475 View commit details
Showing with 140 additions and 35 deletions.
  1. +7 −3 .travis.yml
  2. +18 −6 drupy/objects.py
  3. +18 −8 drupy/runner.py
  4. +23 −15 drupy/targets.py
  5. +4 −0 requirements-dev.in
  6. +16 −0 requirements-dev.txt
  7. +1 −0 requirements.in
  8. +7 −0 requirements.txt
  9. +5 −2 setup.py
  10. 0 tests/__init__.py
  11. +41 −1 tests/objects_test.py
10 changes: 7 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
language: python
python:
- "3.4"
install: python setup.py install
script: py.test
- "3.6"
install:
- pip install -r requirements-dev.txt
- pip install codecov
script: pytest --cov=drupy tests
after_success:
- codecov
24 changes: 18 additions & 6 deletions drupy/objects.py
Original file line number Diff line number Diff line change
@@ -31,8 +31,8 @@ def addDefaults(config, defaults):

# Optionally load support for yaml config files.
try:
import yaml
parsers['.yaml'] = yaml.load
from ruamel import yaml
parsers['.yaml'] = partial(yaml.load, Loader=yaml.RoundTripLoader)
except ImportError:
pass

@@ -329,12 +329,24 @@ class TarballExtract(Applier):
exts = ['.tar.gz', '.tgz', '.tar.bz2', 'tbz2', '.tar.xz', '.tar', '.zip']

def applyTo(self, target):
unpack = setuptools.archive_util.unpack_archive

# Dry run to find longest prefix.
paths = []
def recordPaths(name, destination):
paths.append(name)
return False
unpack(self.path, target, progress_filter=recordPaths)
prefix = len(os.path.commonprefix(paths))

# Actuall unpacking.
def extractFilter(name, destination):
if name.find('/') >= 0:
return target + '/' + name[name.find('/')+1:]
else:
if len(name) <= prefix:
return False
unpack = setuptools.archive_util.unpack_archive
name = name[prefix:]
if name.startswith('/'):
name = name[1:]
return target + '/' + name
unpack(self.path, target, progress_filter=extractFilter)

def isValid(self):
26 changes: 18 additions & 8 deletions drupy/runner.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import collections
import os
import os.path
import shlex
import shutil
import subprocess
import sys
@@ -13,6 +14,7 @@
DBInstallTarget,
SiteBuildTarget,
SiteInstallTarget,
ResetCacheTarget,
)


@@ -53,6 +55,7 @@ def __init__(self):
defaults['overrides-dir'] = defaults['DBUILD_OVERRIDES_DIR']

build_group = self.add_argument_group('Path options')
build_group.add_argument('--drush', dest='drush', type=str, help='Drush command to use for installing sites. (default: drush)', default='drush')
build_group.add_argument('--source-dir', dest='sourceDir', type=str, help='Directory with the site configuration (see README for the config format). (default: ' + defaults['source-dir'] + ')', default=defaults['source-dir'])
build_group.add_argument('--install-dir', dest='installDir', type=str, help='Directory where the project will be built. (default: ' + defaults['install-dir'] + ')', default=defaults['install-dir'])
build_group.add_argument('--downloads-dir', dest='downloadDir', type=str, help='Directory where downloaded files will be stored. (default: [install-dir]/downloads)', default=None)
@@ -131,12 +134,7 @@ def projectSymlinks(self, path, elements, depth=0):
projects = self.options.projectsDir
while (len(dirqueue) > 0):
path, depth, element = dirqueue.pop(0)
if type(element) in (collections.OrderedDict, dict):
if not os.path.exists(path):
os.makedirs(path)
for name, subelement in element.items():
dirqueue.append((path + '/' + name, depth+1, subelement))
else:
if type(element) == str:
if os.path.lexists(path):
os.unlink(path)
target = os.path.join('../' * depth + projects, element)
@@ -146,6 +144,16 @@ def projectSymlinks(self, path, elements, depth=0):
if self.options.verbose:
print("symlink: %s -> %s" % (path, target))
os.symlink(target, path)
else:
if not os.path.exists(path):
os.makedirs(path)
for name, subelement in element.items():
dirqueue.append((path + '/' + name, depth+1, subelement))

def drush(self, arguments):
"""Execute a drush command."""
cmd = shlex.split(self.options.drush)
self.command(cmd + arguments, shell=False)

def command(self, cmd, shell=False):
if self.options.verbose:
@@ -176,12 +184,14 @@ def runBuild(self):

def runInstall(self):
r = resolver.Resolver(self.options)
r.resolve([SiteInstallTarget(self, s) for s in self.options.sites])
r.resolve([SiteInstallTarget(self, s) for s in self.options.sites] +
[ResetCacheTarget(self, self.options.sites)])
r.execute()

def runDBInstall(self):
r = resolver.Resolver(self.options)
r.resolve([DBInstallTarget(self, s) for s in self.options.sites])
r.resolve([DBInstallTarget(self, s) for s in self.options.sites] +
[ResetCacheTarget(self, self.options.sites)])
r.execute()

def runMake(self):
38 changes: 23 additions & 15 deletions drupy/targets.py
Original file line number Diff line number Diff line change
@@ -90,8 +90,7 @@ def build(self):

profile = config['profile']

cmd = ['drush', 'si', '-y', '--sites-subdir='+self.site,
'--db-url=' + db_url]
cmd = ['si', '-y', '--sites-subdir='+self.site, '--db-url=' + db_url]
cmd += [
'--root='+os.path.join(o.installDir, o.documentRoot),
'--account-mail='+config['account-mail'],
@@ -105,7 +104,7 @@ def build(self):
if self.options.devel:
cmd.append('mo_devel_flag=TRUE')

self.runner.command(cmd, shell=False)
self.runner.drush(cmd)

def dependencies(self):
return [SiteInstallTarget(self.runner, self.site)]
@@ -153,6 +152,27 @@ def dependencies(self):
return targets


class ResetCacheTarget(resolver.Target):
def __init__(self, runner, sites):
super().__init__(runner)
self.sites = sites

def dependencies(self):
return [SiteInstallTarget(self.runner, s) for s in self.sites]

def build(self):
""" Call the configured opcache reset URL. """
o = self.options
if not o.opcache_reset_key:
return
try:
url = o.opcache_reset_url + o.opcache_reset_key
urllib.request.urlopen(url)
print("Reset cache called successfully")
except urllib.error.HTTPError as e:
raise Exception('Failed to reset cache on %s: %s' % (url, str(e)))


class SiteInstallTarget(resolver.SiteTarget):
def __init__(self, runner, site):
resolver.SiteTarget.__init__(self, runner, site)
@@ -174,21 +194,9 @@ def dependencies(self):
targets.append(ProfileInstallTarget(self.runner, profile))
return targets

def resetCache(self):
o = self.options
if not o.opcache_reset_key:
return
try:
url = o.opcache_reset_url + o.opcache_reset_key
urllib.request.urlopen(url)
print("Reset cache called successfully")
except urllib.error.HTTPError as e:
raise Exception('Failed to reset cache on %s: %s' % (url, str(e)))

def build(self):
self.runner.ensureDir(self.target)
self.runner.projectSymlinks(self.target, self.links, 2)
self.resetCache()


class CoreBuildTarget(resolver.Target):
4 changes: 4 additions & 0 deletions requirements-dev.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-r requirements.in
pytest
pytest-cov

16 changes: 16 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements-dev.txt requirements-dev.in
#
atomicwrites==1.2.1 # via pytest
attrs==18.2.0 # via pytest
coverage==4.5.2 # via pytest-cov
more-itertools==5.0.0 # via pytest
pluggy==0.8.0 # via pytest
py==1.7.0 # via pytest
pytest-cov==2.6.1
pytest==4.1.0
ruamel.yaml==0.15.85
six==1.12.0 # via more-itertools, pytest
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ruamel.yaml
7 changes: 7 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt requirements.in
#
ruamel.yaml==0.15.85
7 changes: 5 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

setup(
name='drupy',
version='0.4',
version='0.7.1',
description='Python based deployment tool for drupal',
long_description='Fast, multisite capable drupal deployment tool',
author='Roman Zimmermann',
@@ -18,11 +18,14 @@
keywords='drupal drupy build',

url='https://github.com/moreonion/drupy',
download_url='https://github.com/moreonion/drupy/archive/v0.4.tar.gz',
download_url='https://github.com/moreonion/drupy/archive/v0.7.1.tar.gz',

packages=['drupy'],
entry_points={
'console_scripts': ['drupy = drupy.runner:main'],
},
include_package_data=True,
extras_require = {
'yaml': ['ruamel.yaml<=0.15.51'],
}
)
Empty file added tests/__init__.py
Empty file.
42 changes: 41 additions & 1 deletion tests/objects_test.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import os.path
import shutil
from tempfile import mkdtemp
from unittest import TestCase

import pytest

from drupy.objects import DrupalOrgProject
from drupy.objects import DrupalOrgProject, UrllibDownloader, TarballExtract


class DrupalOrgProjectTest(TestCase):
@@ -33,3 +36,40 @@ def test_is_valid(self):
# Invalid package spec without declaring type.
p = DrupalOrgProject(None, dict(dirname='testitt'))
assert not p.isValid()


class TarballExtractTest(TestCase):

def setup_method(self, test_method):
self.testdir = mkdtemp()

def teardown_method(self, test_method):
shutil.rmtree(self.testdir)

def test_libraries(self):
""" Test whether the top-level directory is properly stripped. """
class Fakerunner:
class options:
verbose = False
dl = UrllibDownloader(Fakerunner, config=dict(
url='https://ftp.drupal.org/files/projects/libraries-7.x-2.3.tar.gz'
))
ex = TarballExtract(Fakerunner, config=dict(
localpath = dl.download('', self.testdir).localpath()
))
ex.applyTo(self.testdir + '/libraries')
os.path.exists(self.testdir + '/libraries/libraries.module')

def test_highcharts(self):
""" Highcharts is a zip-file without any directories to strip. """
class Fakerunner:
class options:
verbose = False
dl = UrllibDownloader(Fakerunner, config=dict(
url='http://code.highcharts.com/zips/Highcharts-4.2.7.zip'
))
ex = TarballExtract(Fakerunner, config=dict(
localpath = dl.download('', self.testdir).localpath()
))
ex.applyTo(self.testdir + '/highcharts')
os.path.exists(self.testdir + '/highcharts/js/highcharts.js')