summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Zamotaev <nzamotaev@luxoft.com>2018-07-02 16:46:35 +0300
committerNikolay Zamotaev <nzamotaev@luxoft.com>2018-07-06 12:26:21 +0000
commit73ac5e6e804ad6cda42834eff85d4c60f4791892 (patch)
tree4861fcd23ab85cb56b0df3ee3538b645ed90cfd9
parent91e213c05f314e9267ca0fe0b6d283badca450f7 (diff)
[deployment-server] Added command for manual package upload
Change-Id: Ia81820d32947b4644909a556d29199a5f6112d46 Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r--store/admin.py26
-rw-r--r--store/management/commands/store-upload-package.py127
-rw-r--r--store/utilities.py22
3 files changed, 154 insertions, 21 deletions
diff --git a/store/admin.py b/store/admin.py
index d7712fd..1dbac7f 100644
--- a/store/admin.py
+++ b/store/admin.py
@@ -41,8 +41,7 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from store.models import *
-from utilities import parseAndValidatePackageMetadata
-from utilities import iconPath
+from utilities import parseAndValidatePackageMetadata, writeTempIcon, makeTagList
class CategoryAdminForm(forms.ModelForm):
class Meta:
@@ -160,16 +159,9 @@ class AppAdminForm(forms.ModelForm):
pass
# write icon into file to serve statically
- try:
- if not os.path.exists(iconPath()):
- os.makedirs(iconPath())
- tempicon = open(iconPath(self.appId), 'w')
- tempicon.write(pkgdata['icon'])
- tempicon.flush()
- tempicon.close()
-
- except IOError as error:
- raise forms.ValidationError(_('Validation error: could not write icon file to media directory: %s' % str(error)))
+ success, error = writeTempIcon(self.appId, pkgdata['icon'])
+ if not success:
+ raise forms.ValidationError(_(error))
return cleaned_data
@@ -181,15 +173,7 @@ class AppAdminForm(forms.ModelForm):
m.file.seek(0)
pkgdata = parseAndValidatePackageMetadata(m.file)
- taglist = set()
- if 'binfmt' in pkgdata:
- taglist.add(pkgdata['binfmt'])
- for fields in ('extra','extraSigned'):
- if fields in pkgdata['header']:
- if 'tags' in pkgdata['header'][fields]:
- tags = set(pkgdata['header'][fields]['tags']) #Fill tags list then add them
- taglist = taglist.union(tags)
- m.tags = ",".join(taglist)
+ m.tags = makeTagList(pkgdata)
return m
diff --git a/store/management/commands/store-upload-package.py b/store/management/commands/store-upload-package.py
new file mode 100644
index 0000000..8a174ce
--- /dev/null
+++ b/store/management/commands/store-upload-package.py
@@ -0,0 +1,127 @@
+#############################################################################
+##
+## Copyright (C) 2018 Luxoft
+##
+## This file is part of the Neptune Deployment Server
+##
+## $QT_BEGIN_LICENSE:GPL-QTAS$
+## Commercial License Usage
+## Licensees holding valid commercial Qt Automotive Suite licenses may use
+## this file in accordance with the commercial license agreement provided
+## with the Software or, alternatively, in accordance with the terms
+## contained in a written agreement between you and The Qt Company. For
+## licensing terms and conditions see https://www.qt.io/terms-conditions.
+## For further information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+## SPDX-License-Identifier: GPL-3.0
+##
+#############################################################################
+
+import os
+
+from django.core.management.base import BaseCommand, CommandError
+from django.core.files.base import ContentFile
+from store.models import App, Category, Vendor
+from store.utilities import parseAndValidatePackageMetadata, packagePath, makeTagList, writeTempIcon
+from optparse import make_option
+
+
+class Command(BaseCommand):
+ help = 'Uploads a package to the deployment server. This can be used for batch uploading.'
+ option_list = BaseCommand.option_list + (
+ make_option('--vendor',
+ action='store',
+ type="string",
+ dest='vendor',
+ help='Vendor name'),
+ make_option('--category',
+ action='store',
+ type="string",
+ dest='category',
+ help='Category name'),
+ make_option('--description',
+ action='store',
+ type="string",
+ dest='description',
+ default="Empty description",
+ help='Short package description'),
+ )
+
+ def handle(self, *args, **options):
+ if len(args) != 1:
+ raise CommandError(
+ 'Usage: manage.py store-upload-package --vendor <vendor> --category <category> [--description <short description>] <package>')
+ if (not options['vendor']) or (not options['category']):
+ raise CommandError(
+ 'Usage: manage.py store-upload-package --vendor <vendor> --category <category> [--description <short description>] <package>')
+ category = Category.objects.all().filter(name__exact=options['category'])
+ vendor = Vendor.objects.all().filter(name__exact=options['vendor'])
+ if len(category) == 0:
+ raise CommandError('Non-existing category specified')
+ if len(vendor) == 0:
+ raise CommandError('Non-existing vendor specified')
+
+ try:
+ self.stdout.write('Parsing package %s' % args[0])
+ packagefile = open(args[0], 'rb')
+ pkgdata = parseAndValidatePackageMetadata(packagefile)
+ self.stdout.write(' -> passed validation (internal name: %s)\n' % pkgdata['storeName'])
+ except Exception as error:
+ self.stdout.write(' -> failed: %s\n' % str(error))
+ return 0
+
+ packagefile.seek(0)
+ appId = pkgdata['info']['id']
+ name = pkgdata['storeName']
+ architecture = pkgdata['architecture']
+ description = options['description']
+ tags = makeTagList(pkgdata)
+
+ try:
+ a = App.objects.get(name__exact=name)
+ if a.id != pkgdata['info']['id']:
+ raise CommandError(
+ 'Validation error: the same package name (%s) is already used for application %s' % (
+ name, a.id))
+ except App.DoesNotExist:
+ pass
+
+ success, error = writeTempIcon(appId,pkgdata['icon'])
+ if not success:
+ raise CommandError(error)
+
+ exists = False
+ app = None
+ try:
+ app = App.objects.get(id__exact=appId)
+ exists = True
+ except App.DoesNotExist:
+ pass
+
+ if exists:
+ app.category = category[0]
+ app.vendor = vendor[0]
+ app.name = name
+ app.tags = tags
+ app.description = app.briefDescription = description
+ app.architecture = architecture
+ app.file.save(packagePath(appId), ContentFile(packagefile.read()))
+ app.save()
+ else:
+ app, created = App.objects.get_or_create(name=name, tags=tags, vendor=vendor[0],
+ category=category[0], id=appId,
+ briefDescription=description, description=description,
+ architecture=architecture)
+ app.file.save(packagePath(appId), ContentFile(packagefile.read()))
+ app.save()
diff --git a/store/utilities.py b/store/utilities.py
index b9fa3a4..b571d79 100644
--- a/store/utilities.py
+++ b/store/utilities.py
@@ -53,6 +53,16 @@ def validateTag(tag):
return False
return True
+def makeTagList(pkgdata):
+ taglist = set()
+ for fields in ('extra', 'extraSigned'):
+ if fields in pkgdata['header']:
+ if 'tags' in pkgdata['header'][fields]:
+ tags = set(pkgdata['header'][fields]['tags']) # Fill tags list then add them
+ taglist = taglist.union(tags)
+ tags = ','.join(taglist)
+ return tags
+
def packagePath(appId = None):
path = settings.MEDIA_ROOT + 'packages/'
if appId is not None:
@@ -65,6 +75,18 @@ def iconPath(appId = None):
return path + appId + '.png'
return path
+def writeTempIcon(appId, icon):
+ try:
+ if not os.path.exists(iconPath()):
+ os.makedirs(iconPath())
+ tempicon = open(iconPath(appId), 'w')
+ tempicon.write(icon)
+ tempicon.flush()
+ tempicon.close()
+ return True, None
+ except IOError as error:
+ return False, 'Validation error: could not write icon file to media directory: %s' % str(error)
+
def downloadPath():
return settings.MEDIA_ROOT + 'downloads/'