Skip to content

Commit

Permalink
GitFile stores hashes for object and commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jmclem committed Feb 10, 2014
1 parent 376e0f5 commit 2aa5f6b
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Web interface for songbook generation (see https://github.com/crep4ever/songbook

## Installation

Be sure you have Python and pip installed. Then run `pip install Requirements.txt`.
Be sure you have Python and pip installed. Then run `pip install -r Requirements.txt`.

In order to get the compilation engine, do `git submodule init` and `git submodule update`.

Expand Down
1 change: 1 addition & 0 deletions Requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ Django==1.6.1
South==0.8.4
Unidecode==0.04.14
jsonfield==0.9.20
GitPython==0.3.2.RC1
17 changes: 11 additions & 6 deletions generator/management/commands/importsongs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
sys.path.append(settings.SONG_PROCESSOR_DIR)
from utils.plastex import parsetex
import pprint
import sh
import git
import os
from generator import models
from django.db import transaction
Expand All @@ -22,8 +22,8 @@ class Command(BaseCommand):

def handle(self, *args, **options):

git = sh.git.bake(_cwd=settings.SONGS_LIBRARY_DIR)
filerev = git("rev-parse", "HEAD")
repo = git.Repo(settings.SONGS_LIBRARY_DIR)

This comment has been minimized.

Copy link
@paternal

paternal Jun 16, 2014

Contributor

Cette ligne là signifie que les chansons sont obligatoirement dans un dépôt git, dont la racine est un datadir. Ça me parait trop restrictif, et ne correspond pas à la discussion qu'on a eu sur songbook-core. En fait, je pense que settings.SONGS_LIBRARY_DIR devrait être suffisant comme datadir.

This comment has been minimized.

Copy link
@Luthaf

Luthaf Jun 17, 2014

Contributor

C'est l'ancienne version. On a prévu d'utiliser plusieurs datadirs (#42 (comment)):

  • un pour les chansons privées,
  • un pour les chansons crées depuis le web
  • tout un tas d'autres pour les datadirs externes

Des chansons seront aussi incluses par leur chemin absolu pour les anciennes versions qui sont préférées par les utilisateurs. Je pense m'attaquer a ce problème des que le CSS est réglé.

gitcmd = repo.git

for root, dirs, filenames in os.walk(settings.SONGS_LIBRARY_DIR,
topdown=True,
Expand All @@ -32,7 +32,7 @@ def handle(self, *args, **options):

for filename in filenames:
if filename.lower().endswith(".sg"):
filepath = os.path.join(root, filename)
filepath = os.path.realpath(os.path.join(root, filename))
filepath_rel = os.path.relpath(filepath, settings.SONGS_LIBRARY_DIR)
try:
data = parsetex(filepath)
Expand Down Expand Up @@ -77,8 +77,13 @@ def handle(self, *args, **options):
+ song_model.title)

gitfile = models.GitFile()
gitfile.file_path = filepath_rel
gitfile.file_version = filerev

gitfile.object_hash = gitcmd.hash_object(filepath)

gitfile.commit_hash = gitcmd.log("-1",
"--pretty=format:%H",
"--", filepath)
gitfile.file_path = filepath

song_model.file = gitfile

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Deleting field 'GitFile.file_version'
db.delete_column(u'generator_gitfile', 'file_version')

# Adding field 'GitFile.commit_hash'
db.add_column(u'generator_gitfile', 'commit_hash',
self.gf('django.db.models.fields.CharField')(default=0, max_length=20),
keep_default=False)

# Adding field 'GitFile.object_hash'
db.add_column(u'generator_gitfile', 'object_hash',
self.gf('django.db.models.fields.CharField')(default=0, max_length=20),
keep_default=False)


def backwards(self, orm):
# Adding field 'GitFile.file_version'
db.add_column(u'generator_gitfile', 'file_version',
self.gf('django.db.models.fields.CharField')(default=0, max_length=20),
keep_default=False)

# Deleting field 'GitFile.commit_hash'
db.delete_column(u'generator_gitfile', 'commit_hash')

# Deleting field 'GitFile.object_hash'
db.delete_column(u'generator_gitfile', 'object_hash')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': '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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'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'})
},
u'generator.artist': {
'Meta': {'ordering': "['name']", 'object_name': 'Artist'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
},
u'generator.gitfile': {
'Meta': {'object_name': 'GitFile'},
'commit_hash': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'file_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_hash': ('django.db.models.fields.CharField', [], {'max_length': '20'})
},
u'generator.itemsinsongbook': {
'Meta': {'object_name': 'ItemsInSongbook'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'item_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
'item_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'rank': ('django.db.models.fields.IntegerField', [], {}),
'songbook': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['generator.Songbook']"})
},
u'generator.profile': {
'Meta': {'object_name': 'Profile'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'songbooks': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'songbooks'", 'blank': 'True', 'through': u"orm['generator.SongbooksByUser']", 'to': u"orm['generator.Songbook']"}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
},
u'generator.section': {
'Meta': {'object_name': 'Section'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'})
},
u'generator.song': {
'Meta': {'ordering': "['title']", 'object_name': 'Song'},
'artist': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'songs'", 'to': u"orm['generator.Artist']"}),
'capo': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'file': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['generator.GitFile']", 'unique': 'True', 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'max_length': '7', 'null': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'generator.songbook': {
'Meta': {'object_name': 'Songbook'},
'bookoptions': ('jsonfield.fields.JSONField', [], {}),
'booktype': ('django.db.models.fields.CharField', [], {'default': "'chrd'", 'max_length': '4'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'items': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'items'", 'blank': 'True', 'through': u"orm['generator.ItemsInSongbook']", 'to': u"orm['contenttypes.ContentType']"}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100'}),
'template': ('django.db.models.fields.CharField', [], {'default': "'patacrep.tmpl'", 'max_length': '100'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'users'", 'blank': 'True', 'through': u"orm['generator.SongbooksByUser']", 'to': u"orm['generator.Profile']"})
},
u'generator.songbooksbyuser': {
'Meta': {'object_name': 'SongbooksByUser'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_owner': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'songbook': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['generator.Songbook']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['generator.Profile']"})
}
}

complete_apps = ['generator']
6 changes: 4 additions & 2 deletions generator/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,14 @@ class GitFile(models.Model):
"""Hold the information about the file object in a git repository.
Attributes:
file_path string path of the file in the songs repository
file_version string version of the file as currently known in db
commit_hash string hash of the commit the file was imported from
object_hash string hash of the file object
"""

# We use a CharField here, not FileField, we take care of the file.
file_path = models.CharField(max_length=500)
file_version = models.CharField(max_length=20)
commit_hash = models.CharField(max_length=20)
object_hash = models.CharField(max_length=20)

def __unicode__(self):
return "{0}:{1}".format(self.file_version, self.file_path)

2 comments on commit 2aa5f6b

@Luthaf
Copy link
Contributor

@Luthaf Luthaf commented on 2aa5f6b Feb 10, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pourquoi avoir mis à la fois un hash du commit et un hash du fichier ?

Et une autre question : pour retrouver une version particulière du fichier, il suffit d'avoir le hash du commit ou pas ? Parce qu'il faudra alors que je l'ajoute au modèle ItemsInSongbook.

@jmclem
Copy link
Contributor Author

@jmclem jmclem commented on 2aa5f6b Feb 10, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pourquoi avoir mis à la fois un hash du commit et un hash du fichier ?

Pour l'instant (ça peut changer, c'est pas encore fait), j'envisage d'utiliser le hash du fichier pour accéder au contenu (ancien ou actuel) pour la génération du carnet.

Je pense utiliser le chemin et le hash du commit pour détecter si il y a de nouvelles versions du fichier.

Pour le lien depuis ItemsInSongbook, voir ici ce commentaire.

Please sign in to comment.