summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2010-03-03 06:55:54 -0600
committerDan McGee <dan@archlinux.org>2010-03-03 06:55:54 -0600
commit83b7b94c0b062b0c209ea47de9180f28db6dbb81 (patch)
tree10996dee5eadc35603a59bfcd8a2c7d55b3d2de1
parent558fad8bee8b456eef23532ef2c15f897414be86 (diff)
parentf7e15ed728d7c5e3470f6127cc21e64baefcbfb2 (diff)
Merge branch 'master' into cdn-jquery
Conflicts: templates/todolists/view.html
-rw-r--r--[-rwxr-xr-x]devel/management/commands/reporead.py90
-rw-r--r--main/migrations/0007_add_files_last_update.py193
-rw-r--r--main/models.py1
-rw-r--r--media/arch.css47
-rw-r--r--media/titlelogo.pngbin4190 -> 4502 bytes
-rw-r--r--packages/views.py16
-rw-r--r--templates/404.html1
-rw-r--r--templates/devel/index.html1
-rw-r--r--templates/devel/mirrorlist.html1
-rw-r--r--templates/news/add.html1
-rw-r--r--templates/news/delete.html1
-rw-r--r--templates/news/view.html1
-rw-r--r--templates/packages/details.html26
-rw-r--r--templates/packages/files-list.html12
-rw-r--r--templates/packages/files.html8
-rw-r--r--templates/packages/flag.html3
-rw-r--r--templates/packages/flagged.html1
-rw-r--r--templates/todolists/list.html1
-rw-r--r--templates/todolists/todolist_confirm_delete.html1
-rw-r--r--templates/todolists/view.html3
-rw-r--r--todolists/views.py8
-rw-r--r--urls.py3
22 files changed, 322 insertions, 97 deletions
diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py
index 3ff6f596..34b291eb 100755..100644
--- a/devel/management/commands/reporead.py
+++ b/devel/management/commands/reporead.py
@@ -6,7 +6,7 @@ Parses a repo.db.tar.gz file and updates the Arch database with the relevant
changes.
Usage: ./manage.py reporead ARCH PATH
- ARCH: architecture to update, and can be one of: i686, x86_64
+ ARCH: architecture to update; must be available in the database
PATH: full path to the repo.db.tar.gz file.
Example:
@@ -55,6 +55,8 @@ class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('-f', '--force', action='store_true', dest='force', default=False,
help='Force a re-import of data for all packages instead of only new ones. Will not touch the \'last updated\' value.'),
+ make_option('--filesonly', action='store_true', dest='filesonly', default=False,
+ help='Load filelists if they are outdated, but will not add or remove any packages. Will not touch the \'last updated\' value.'),
)
help = "Runs a package repository import for the given arch and file."
args = "<arch> <filename>"
@@ -132,7 +134,7 @@ class Pkg(object):
return None
-def populate_pkg(dbpkg, repopkg, timestamp=None):
+def populate_pkg(dbpkg, repopkg, force=False, timestamp=None):
dbpkg.pkgbase = repopkg.base
dbpkg.pkgver = repopkg.ver
dbpkg.pkgrel = repopkg.rel
@@ -153,9 +155,9 @@ def populate_pkg(dbpkg, repopkg, timestamp=None):
dbpkg.needupdate = False
dbpkg.last_update = timestamp
dbpkg.save()
- # files are not in the repo.db.tar.gz
- #for x in repopkg.files:
- # dbpkg.packagefile_set.create(path=x)
+
+ populate_files(dbpkg, repopkg, force=force)
+
dbpkg.packagedepend_set.all().delete()
if 'depends' in repopkg.__dict__:
for y in repopkg.depends:
@@ -168,8 +170,22 @@ def populate_pkg(dbpkg, repopkg, timestamp=None):
dbpkg.packagedepend_set.create(depname=dpname, depvcmp=dpvcmp)
logger.debug('Added %s as dep for pkg %s' % (dpname,repopkg.name))
-
-def db_update(archname, pkgs, force):
+def populate_files(dbpkg, repopkg, force=False):
+ if not force:
+ if not dbpkg.files_last_update or not dbpkg.last_update:
+ pass
+ elif dbpkg.files_last_update > dbpkg.last_update:
+ return
+ # only delete files if we are reading a DB that contains them
+ if 'files' in repopkg.__dict__:
+ dbpkg.packagefile_set.all().delete()
+ logger.info("adding %d files for package %s" % (len(repopkg.files), dbpkg.pkgname))
+ for x in repopkg.files:
+ dbpkg.packagefile_set.create(path=x)
+ dbpkg.files_last_update = datetime.now()
+ dbpkg.save()
+
+def db_update(archname, pkgs, options):
"""
Parses a list and updates the Arch dev database accordingly.
@@ -178,6 +194,8 @@ def db_update(archname, pkgs, force):
"""
logger.info('Updating Arch: %s' % archname)
+ force = options.get('force', False)
+ filesonly = options.get('filesonly', False)
repository = Repo.objects.get(name__iexact=pkgs[0].repo)
architecture = Arch.objects.get(name__iexact=archname)
dbpkgs = Package.objects.filter(arch=architecture, repo=repository)
@@ -217,19 +235,22 @@ def db_update(archname, pkgs, force):
if dbpercent < 75.0:
logger.warning(".db.tar.gz has %.1f%% the number of packages in the web database." % dbpercent)
-
- for p in [x for x in pkgs if x.name in in_sync_not_db]:
- logger.info("Adding package %s", p.name)
- pkg = Package(pkgname = p.name, arch = architecture, repo = repository)
- populate_pkg(pkg, p, timestamp=datetime.now())
-
- # packages in database and not in syncdb (remove from database)
- logger.debug("Set theory: Packages in database not in syncdb")
- in_db_not_sync = dbset - syncset
- for p in in_db_not_sync:
- logger.info("Removing package %s from database", p)
- Package.objects.get(
- pkgname=p, arch=architecture, repo=repository).delete()
+
+ if not filesonly:
+ # packages in syncdb and not in database (add to database)
+ logger.debug("Set theory: Packages in syncdb not in database")
+ for p in [x for x in pkgs if x.name in in_sync_not_db]:
+ logger.info("Adding package %s", p.name)
+ pkg = Package(pkgname = p.name, arch = architecture, repo = repository)
+ populate_pkg(pkg, p, timestamp=datetime.now())
+
+ # packages in database and not in syncdb (remove from database)
+ logger.debug("Set theory: Packages in database not in syncdb")
+ in_db_not_sync = dbset - syncset
+ for p in in_db_not_sync:
+ logger.info("Removing package %s from database", p)
+ Package.objects.get(
+ pkgname=p, arch=architecture, repo=repository).delete()
# packages in both database and in syncdb (update in database)
logger.debug("Set theory: Packages in database and syncdb")
@@ -240,15 +261,21 @@ def db_update(archname, pkgs, force):
timestamp = None
# for a force, we don't want to update the timestamp.
# for a non-force, we don't want to do anything at all.
- if ''.join((p.ver,p.rel)) == ''.join((dbp.pkgver,dbp.pkgrel)):
+ if filesonly:
+ pass
+ elif ''.join((p.ver,p.rel)) == ''.join((dbp.pkgver,dbp.pkgrel)):
if not force:
continue
else:
timestamp = datetime.now()
- logger.info("Updating package %s in database", p.name)
pkg = Package.objects.get(
pkgname=p.name,arch=architecture, repo=repository)
- populate_pkg(pkg, p, timestamp=timestamp)
+ if filesonly:
+ logger.info("Possibly populating files for package %s in database", p.name)
+ populate_files(pkg, p)
+ else:
+ logger.info("Updating package %s in database", p.name)
+ populate_pkg(pkg, p, force=force, timestamp=timestamp)
logger.info('Finished updating Arch: %s' % archname)
@@ -297,13 +324,18 @@ def parse_repo(repopath):
logger.info("Reading repo tarfile %s", repopath)
filename = os.path.split(repopath)[1]
- rindex = filename.rindex('.db.tar.gz')
- reponame = filename[:rindex]
-
+ m = re.match(r"^(.*)\.(db|files)\.tar\.(.*)$", filename)
+ if m:
+ reponame = m.group(1)
+ else:
+ logger.error("File does not have the proper extension")
+ raise SomethingFishyException("File does not have the proper extension")
+
repodb = tarfile.open(repopath,"r:gz")
## assuming well formed tar, with dir first then files after
## repo-add enforces this
logger.debug("Starting package parsing")
+ dbfiles = ('desc', 'depends', 'files')
pkgs = []
tpkg = None
while True:
@@ -321,7 +353,8 @@ def parse_repo(repopath):
# set new tpkg
tpkg = StringIO()
if tarinfo.isreg():
- if os.path.split(tarinfo.name)[1] in ('desc','depends'):
+ fname = os.path.split(tarinfo.name)[1]
+ if fname in dbfiles:
tpkg.write(repodb.extractfile(tarinfo).read())
tpkg.write('\n') # just in case
repodb.close()
@@ -353,11 +386,10 @@ def read_repo(primary_arch, file, options):
logger.warning("Package %s arch = %s" % (
package.name,package.arch))
#package.arch = primary_arch
- f = options.get('force', False)
logger.info('Starting database updates.')
for (arch, pkgs) in packages_arches.items():
if len(pkgs) > 0:
- db_update(arch, pkgs, f)
+ db_update(arch, pkgs, options)
logger.info('Finished database updates.')
return 0
diff --git a/main/migrations/0007_add_files_last_update.py b/main/migrations/0007_add_files_last_update.py
new file mode 100644
index 00000000..36f99c26
--- /dev/null
+++ b/main/migrations/0007_add_files_last_update.py
@@ -0,0 +1,193 @@
+from south.db import db
+from django.db import models
+from main.models import *
+
+class Migration:
+ def forwards(self, orm):
+ # Adding field 'Package.files_last_update'
+ db.add_column('packages', 'files_last_update', orm['main.package:files_last_update'])
+
+ def backwards(self, orm):
+ # Deleting field 'Package.files_last_update'
+ db.delete_column('packages', 'files_last_update')
+
+ models = {
+ 'auth.group': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)"},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'main.altforum': {
+ 'Meta': {'db_table': "'alt_forums'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'language': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.arch': {
+ 'Meta': {'db_table': "'arches'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ 'main.donor': {
+ 'Meta': {'db_table': "'donors'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ 'main.externalproject': {
+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
+ },
+ 'main.mirror': {
+ 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'admin_email': ('django.db.models.fields.EmailField', [], {'max_length': '255', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'isos': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'notes': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+ 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'})
+ },
+ 'main.mirrorprotocol': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '10'})
+ },
+ 'main.mirrorrsync': {
+ 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rsync_ips'", 'to': "orm['main.Mirror']"})
+ },
+ 'main.mirrorurl': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mirror': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['main.Mirror']"}),
+ 'protocol': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'urls'", 'to': "orm['main.MirrorProtocol']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.news': {
+ 'Meta': {'db_table': "'news'"},
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'news_author'", 'to': "orm['auth.User']"}),
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'postdate': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.package': {
+ 'Meta': {'db_table': "'packages'"},
+ 'arch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Arch']"}),
+ 'build_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'compressed_size': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
+ 'files_last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'installed_size': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
+ 'last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'maintained_packages'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'needupdate': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'pkgbase': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'pkgdesc': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'pkgname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'repo': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Repo']"}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.packagedepend': {
+ 'Meta': {'db_table': "'package_depends'"},
+ 'depname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'depvcmp': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"})
+ },
+ 'main.packagefile': {
+ 'Meta': {'db_table': "'package_files'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"})
+ },
+ 'main.press': {
+ 'Meta': {'db_table': "'press'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.repo': {
+ 'Meta': {'db_table': "'repos'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ 'main.signoff': {
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}),
+ 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.todolist': {
+ 'Meta': {'db_table': "'todolists'"},
+ 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'date_added': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'main.todolistpkg': {
+ 'Meta': {'unique_together': "(('list', 'pkg'),)", 'db_table': "'todolist_pkgs'"},
+ 'complete': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Todolist']"}),
+ 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"})
+ },
+ 'main.userprofile': {
+ 'Meta': {'db_table': "'user_profiles'"},
+ 'alias': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'allowed_repos': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Repo']", 'blank': 'True'}),
+ 'favorite_distros': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'interests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'languages': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'notify': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+ 'other_contact': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+ 'picture': ('django.db.models.fields.files.FileField', [], {'default': "'devs/silhouette.png'", 'max_length': '100'}),
+ 'public_email': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'roles': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'userprofile_user'", 'unique': 'True', 'to': "orm['auth.User']"}),
+ 'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'yob': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['main']
diff --git a/main/models.py b/main/models.py
index 373c3e00..dd37f885 100644
--- a/main/models.py
+++ b/main/models.py
@@ -174,6 +174,7 @@ class Package(models.Model):
installed_size = models.PositiveIntegerField(null=True)
build_date = models.DateTimeField(null=True)
last_update = models.DateTimeField(null=True, blank=True)
+ files_last_update = models.DateTimeField(null=True, blank=True)
license = models.CharField(max_length=255)
objects = PackageManager()
class Meta:
diff --git a/media/arch.css b/media/arch.css
index 9b4759d3..a03d2448 100644
--- a/media/arch.css
+++ b/media/arch.css
@@ -344,53 +344,6 @@ blockquote.code {
padding: 5px;
font-family: "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Courier, "Courier New", Monospace;
}
-/*
- * Wiki Styles
- */
-h1.wiki {
- border-bottom: 1px solid #46494d;
-}
-div.wikifoot_l {
- font-size: x-small;
- text-align: left;
- padding-top: 25px;
-}
-div.wikifoot_r {
- font-size: x-small;
- text-align: right;
- float: right;
- padding-top: 25px;
-}
-.wikibody {
- padding-top: 15px;
-}
-.wikibody ol {
- padding-left: 28px;
- padding-top: 0px;
-}
-.wikibody ul {
- padding-left: 25px;
- padding-top: 0px;
-}
-.wikibody dd {
- padding-left: 30px;
-}
-.wikibody pre code {
- background: #c1c3f6;
- border: 1px solid #8faecd;
- margin-left: auto;
- margin-right: auto;
- white-space: nowrap;
- padding: 5px;
- font-family: "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Courier, "Courier New", Monospace;
-}
-.wikibody blockquote {
- padding-left: 30px;
-}
-.wikibody td {
- padding: 5px;
- border: 1px solid black;
-}
td.signoff_yes {
font-size: large;
diff --git a/media/titlelogo.png b/media/titlelogo.png
index fa173795..be7f14c7 100644
--- a/media/titlelogo.png
+++ b/media/titlelogo.png
Binary files differ
diff --git a/packages/views.py b/packages/views.py
index 97929ed3..8a2b4ec3 100644
--- a/packages/views.py
+++ b/packages/views.py
@@ -7,6 +7,7 @@ from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from django.contrib.auth.decorators import permission_required
from django.contrib.admin.widgets import AdminDateWidget
+from django.views.decorators.vary import vary_on_headers
from django.views.generic import list_detail
from django.db.models import Q
@@ -60,7 +61,7 @@ def update(request):
def details(request, name='', repo='', arch=''):
if all([name, repo, arch]):
- pkg= get_object_or_404(Package,
+ pkg = get_object_or_404(Package,
pkgname=name, repo__name__iexact=repo, arch__name=arch)
return render_to_response('packages/details.html', RequestContext(
request, {'pkg': pkg, }))
@@ -178,10 +179,15 @@ def search(request, page=None):
template_object_name="package",
extra_context=page_dict)
-def files(request, pkgid):
- pkg = get_object_or_404(Package, id=pkgid)
- files = PackageFile.objects.filter(pkg=pkgid)
- return render_to_response('packages/files.html', RequestContext(request, {'pkg':pkg,'files':files}))
+@vary_on_headers('X-Requested-With')
+def files(request, name='', repo='', arch=''):
+ pkg = get_object_or_404(Package,
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ files = PackageFile.objects.filter(pkg=pkg).order_by('path')
+ template = 'packages/files.html'
+ if request.is_ajax():
+ template = 'packages/files-list.html'
+ return render_to_response(template, RequestContext(request, {'pkg':pkg,'files':files}))
@permission_required('main.change_package')
def unflag(request, pkgid):
diff --git a/templates/404.html b/templates/404.html
index bc50f69b..9e389ba9 100644
--- a/templates/404.html
+++ b/templates/404.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Page Not Found{% endblock %}
{% block content %}
<div class="box">
diff --git a/templates/devel/index.html b/templates/devel/index.html
index 1203d8a6..12c0791e 100644
--- a/templates/devel/index.html
+++ b/templates/devel/index.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Developer Dashboard{% endblock %}
{% block head %}
{% load cdn %}{% jquery %}
diff --git a/templates/devel/mirrorlist.html b/templates/devel/mirrorlist.html
index 01699daf..630d018d 100644
--- a/templates/devel/mirrorlist.html
+++ b/templates/devel/mirrorlist.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Mirror Overview{% endblock %}
{% block content %}
<div class="greybox">
diff --git a/templates/news/add.html b/templates/news/add.html
index daa75871..ef3f211c 100644
--- a/templates/news/add.html
+++ b/templates/news/add.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - {% if form.instance.id %}Edit{% else %}Add{% endif %} News{% endblock %}
{% block content %}
<div class="greybox">
diff --git a/templates/news/delete.html b/templates/news/delete.html
index 0f48f8bb..c3824a26 100644
--- a/templates/news/delete.html
+++ b/templates/news/delete.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Delete News{% endblock %}
{% block content %}
<div class="greybox">
diff --git a/templates/news/view.html b/templates/news/view.html
index 281d8a7e..2f7c3d87 100644
--- a/templates/news/view.html
+++ b/templates/news/view.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - {{ news.title }}{% endblock %}
{% block content %}
<div class="box">
diff --git a/templates/packages/details.html b/templates/packages/details.html
index 5c3c9497..9b7a0492 100644
--- a/templates/packages/details.html
+++ b/templates/packages/details.html
@@ -1,6 +1,5 @@
{% extends "base.html" %}
-{% load package_extras %}
-{% block title %}Pkg: {{ pkg.pkgname }} - Arch Linux Package Details{% endblock %}
+{% block title %}Arch Linux - {{ pkg.pkgname }} {{ pkg.pkgver }}-{{ pkg.pkgrel }} - Package Details{% endblock %}
{% block content %}
<div class="box">
<h2 class="title">{{ pkg.pkgname }} {{ pkg.pkgver }}-{{ pkg.pkgrel }}</h2>
@@ -9,7 +8,6 @@
<li><a href="{{ pkg.get_arch_svn_link }}">SVN Entries ({{pkg.repo|lower}}-{{pkg.arch}})</a></li>
<li><a href="{{ pkg.get_trunk_svn_link }}">SVN Entries (trunk)</a></li>
<li><a href="{{ pkg.get_bugs_link }}">Bug Reports</a></li>
- <!-- <li><a href="/packages/files/{{ pkg.id }}/">View File List</a></li> -->
<li>
{% if pkg.needupdate %}
<span style="font-size:x-small"><em>This package has been flagged out-of-date</em></span>
@@ -79,7 +77,7 @@
{% ifequal depend.pkg None %}
<li>{{ depend.dep.depname }} (virtual)</li>
{% else %}
- <li><a href="{{ depend.pkg.get_absolute_url }}">{{ depend.dep.depname }}</a>{{ depend.dep.depvcmp }}</li>
+ <li><a href="{{ depend.pkg.get_absolute_url }}">{{ depend.dep.depname }}</a>{{ depend.dep.depvcmp }}{% ifequal depend.pkg.repo.name "Testing" %} (testing){% endifequal %}</li>
{% endifequal %}
{% endfor %}
</ul>
@@ -94,7 +92,7 @@
{% if rqdby %}
<ul style="font-size:small;list-style:none">
{% for req in rqdby %}
- <li><a href="{{req.get_absolute_url}}">{{ req.pkgname }}{% ifequal req.repo.name "Testing" %} (testing){% endifequal %}{% ifequal req.repo.name "Unstable" %} (unstable){% endifequal %}</a></li>
+ <li><a href="{{req.get_absolute_url}}">{{ req.pkgname }}</a>{% ifequal req.repo.name "Testing" %} (testing){% endifequal %}</li>
{% endfor %}
</ul>
{% endif %}
@@ -103,6 +101,24 @@
</td>
</tr>
</table>
+ <div class="listing" id="filelist">
+ <h4>Files:</h4>
+ <p style="padding: 10px 20px;">
+ <a id="filelink" href="files/">View File List</a>
+ </p>
+ </div>
</div>
+<script type="text/javascript" src="/media/jquery-1.4.1.min.js"></script>
+<script type="text/javascript">
+function ajaxifyFiles() {
+ $('#filelink').click(function(event) {
+ event.preventDefault();
+ $.get(this.href, function(data) {
+ $('#filelist').html(data);
+ });
+ });
+}
+$(document).ready(ajaxifyFiles);
+</script>
{% endblock %}
diff --git a/templates/packages/files-list.html b/templates/packages/files-list.html
new file mode 100644
index 00000000..d26a11e9
--- /dev/null
+++ b/templates/packages/files-list.html
@@ -0,0 +1,12 @@
+<div class="listing" id="filelist">
+ <h4>Files:</h4>
+ {% if files.count %}
+ <ul style="font-size:small;list-style:none">
+ {% for file in files %}
+ <li>{{ file.path }}</li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p style="padding: 10px 20px;">No filelist available.</p>
+ {% endif %}
+</div>
diff --git a/templates/packages/files.html b/templates/packages/files.html
index 145bcf24..2fff5ff1 100644
--- a/templates/packages/files.html
+++ b/templates/packages/files.html
@@ -1,11 +1,9 @@
{% extends "base.html" %}
-{% block title %}Pkg: {{ pkg.pkgname }} - Arch Linux Package File List{% endblock %}
+{% block title %}Arch Linux - {{ pkg.pkgname }} {{ pkg.pkgver }}-{{ pkg.pkgrel }} - Package File List{% endblock %}
{% block content %}
<div class="box">
- <h3>Viewing Files: {{ pkg.pkgname }} {{ pkg.pkgver }}-{{ pkg.pkgrel }}</h3>
- {% for file in files %}
- {{ file.path }}<br />
- {% endfor %}
+ <h2 class="title">{{ pkg.pkgname }} {{ pkg.pkgver }}-{{ pkg.pkgrel }}</h2>
+ {% include "packages/files-list.html" %}
</div>
{% endblock %}
diff --git a/templates/packages/flag.html b/templates/packages/flag.html
index 0bea7396..1071fdf8 100644
--- a/templates/packages/flag.html
+++ b/templates/packages/flag.html
@@ -1,5 +1,6 @@
{% extends "base.html" %}
{% block title %}Arch Linux - Flag Package - {{ pkg.pkgname }}{% endblock %}
+
{% block content %}
<div>
{% if confirmed %}
@@ -22,7 +23,7 @@
{{form}}
</table>
<input type="submit" value=" Confirm " />
- <br />
</form>
{% endif %}
+</div>
{% endblock %}
diff --git a/templates/packages/flagged.html b/templates/packages/flagged.html
index 738b633f..64cb2452 100644
--- a/templates/packages/flagged.html
+++ b/templates/packages/flagged.html
@@ -1,5 +1,6 @@
{% extends "base.html" %}
{% block title %}Arch Linux - Flag Package - {{ pkg.pkgname }}{% endblock %}
+
{% block content %}
<p>
{{pkg.pkgname}} on {{pkg.arch}} has already been flagged out of date.
diff --git a/templates/todolists/list.html b/templates/todolists/list.html
index 9b423342..ffbab2af 100644
--- a/templates/todolists/list.html
+++ b/templates/todolists/list.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Todo Lists{% endblock %}
{% block content %}
<div class="greybox">
diff --git a/templates/todolists/todolist_confirm_delete.html b/templates/todolists/todolist_confirm_delete.html
index bfa3dbab..c0742d2b 100644
--- a/templates/todolists/todolist_confirm_delete.html
+++ b/templates/todolists/todolist_confirm_delete.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Delete Todo List{% endblock %}
{% block content %}
<div class="greybox">
diff --git a/templates/todolists/view.html b/templates/todolists/view.html
index 6f85c231..5af6da81 100644
--- a/templates/todolists/view.html
+++ b/templates/todolists/view.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% block title %}Arch Linux - Todo - {{ list.name }}{% endblock %}
{% block content %}
<div class="greybox">
@@ -10,7 +11,7 @@
<a href="/todo/edit/{{list.id}}/">Edit Todo List</a>
{% endif %}
</div>
- <h2 class="title">ToDo List: {{ list.name }}</h2>
+ <h2 class="title">Todo List: {{ list.name }}</h2>
<table id="todotable" class="results" width="100%">
<thead>
<tr>
diff --git a/todolists/views.py b/todolists/views.py
index a38ec0d7..f176e39c 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -5,6 +5,7 @@ from django.template import RequestContext
from django.core.mail import send_mail
from django.shortcuts import get_object_or_404, render_to_response
from django.contrib.auth.decorators import login_required, permission_required
+from django.views.decorators.vary import vary_on_headers
from django.views.generic.create_update import delete_object
from django.template import Context, loader
from django.utils import simplejson
@@ -31,6 +32,7 @@ class TodoListForm(forms.Form):
@login_required
+@vary_on_headers('X-Requested-With')
def flag(request, listid, pkgid):
list = get_object_or_404(Todolist, id=listid)
pkg = get_object_or_404(TodolistPkg, id=pkgid)
@@ -76,7 +78,7 @@ def add(request):
form = TodoListForm()
page_dict = {
- 'title': 'Add To-do List',
+ 'title': 'Add Todo List',
'form': form,
'submit_text': 'Create List'
}
@@ -115,7 +117,7 @@ def edit(request, list_id):
'packages': todo_list.package_names,
})
page_dict = {
- 'title': 'Edit To-do List "%s"' % todo_list.name,
+ 'title': 'Edit Todo List: %s' % todo_list.name,
'form': form,
'submit_text': 'Save List'
}
@@ -129,7 +131,7 @@ def delete_todolist(request, object_id):
def send_todolist_email(todo):
'''Sends an e-mail to the maintainer of a package notifying them that the
- package has been added to a to-do list'''
+ package has been added to a todo list'''
if not todo.pkg.maintainer:
return
diff --git a/urls.py b/urls.py
index ec04edce..e53d918a 100644
--- a/urls.py
+++ b/urls.py
@@ -27,7 +27,6 @@ urlpatterns = patterns('',
(r'^packages/flag/(\d+)/$', 'packages.views.flag'),
(r'^packages/flaghelp/$', 'packages.views.flaghelp'),
(r'^packages/unflag/(\d+)/$', 'packages.views.unflag'),
- (r'^packages/files/(\d+)/$', 'packages.views.files'),
(r'^packages/signoffs/$', 'packages.views.signoffs'),
(r'^packages/signoff_package/(?P<arch>[A-z0-9]+)/(?P<pkgname>[A-z0-9\-+.]+)/$',
'packages.views.signoff_package'),
@@ -46,6 +45,8 @@ urlpatterns = patterns('',
'packages.views.details'),
(r'^packages/(?P<repo>[A-z0-9\-]+)/(?P<arch>[A-z0-9]+)/(?P<name>[A-z0-9\-+.]+)/$',
'packages.views.details'),
+ (r'^packages/(?P<repo>[A-z0-9\-]+)/(?P<arch>[A-z0-9]+)/(?P<name>[A-z0-9\-+.]+)/files/$',
+ 'packages.views.files'),
(r'^packages/(?P<repo>[A-z0-9\-]+)/(?P<arch>[A-z0-9]+)/(?P<name>[A-z0-9\-+.]+)/maintainer/$',
'packages.views.getmaintainer'),