Merge Request #36

Closed
softwarepublico/colab!36
Created by Carolina

Trac indexing

Milestone: None

Closed by Alexandre Barbosa

Changes were not merged into target branch

Commits (34)
7 participants
ci/install_solr.sh
@@ -8,14 +8,14 @@ download() { @@ -8,14 +8,14 @@ download() {
8 FILE="$2.tgz" 8 FILE="$2.tgz"
9 if [ -f $FILE ]; 9 if [ -f $FILE ];
10 then 10 then
11 - echo "File $FILE exists."  
12 - tar -zxf $FILE 11 + echo "File $FILE exists."
  12 + tar -zxf $FILE
13 else 13 else
14 - echo "Downloading solr from $1..."  
15 - curl -O $1  
16 - tar -zxf $FILE 14 + echo "File $FILE does not exist. Downloading solr from $1..."
  15 + curl -O $1
  16 + tar -zxf $FILE
17 fi 17 fi
18 - echo "Downloaded" 18 + echo "Downloaded!"
19 } 19 }
20 20
21 is_solr_up(){ 21 is_solr_up(){
@@ -183,11 +183,7 @@ download_and_run() { @@ -183,11 +183,7 @@ download_and_run() {
183 # copies custom configurations 183 # copies custom configurations
184 for file in $SOLR_CONFS 184 for file in $SOLR_CONFS
185 do 185 do
186 - if [ -d $file ]  
187 - then  
188 - cp $file/* $dir_name/example/solr/$dir_conf  
189 - echo "Copied directory $file into solr conf directory."  
190 - elif [ -f $file ] 186 + if [ -f $file ]
191 then 187 then
192 cp $file $dir_name/example/solr/$dir_conf 188 cp $file $dir_name/example/solr/$dir_conf
193 echo "Copied $file into solr conf directory." 189 echo "Copied $file into solr conf directory."
colab/proxy/trac/data_api.py
  1 +# -*- coding: utf-8 -*-
  2 +from re import match
  3 +
  4 +from django.db import connections
  5 +
  6 +from colab.proxy.trac.models import Attachment, Revision, Ticket, Wiki
1 from colab.proxy.utils.proxy_data_api import ProxyDataAPI 7 from colab.proxy.utils.proxy_data_api import ProxyDataAPI
2 8
3 9
4 class TracDataAPI(ProxyDataAPI): 10 class TracDataAPI(ProxyDataAPI):
5 11
6 def fetch_data(self): 12 def fetch_data(self):
7 - pass 13 + """ This is the pricipal method whose function is just make the call the
  14 + other methods.
  15 +
  16 + """
  17 + connection = connections['trac']
  18 + cursor = connection.cursor()
  19 + self.fetch_data_wiki(cursor)
  20 + self.fetch_data_attachment(cursor)
  21 + self.fetch_data_ticket(cursor)
  22 + self.fetch_data_revision(cursor)
  23 +
  24 + def fetch_data_attachment(self, empty_cursor):
  25 + """ This method is responsible for seeking the attachment data in
  26 +        trac database and transfer them to the colab database.
  27 +
  28 + :param empty_cursor: A cursor coming from connectinos, it is necessary
  29 +         import the connections library from django.db, with it we can run
  30 +         sql commands.
  31 +
  32 +        :returns: Return is an attachment object with your saved data
  33 +         in the colab database.
  34 +
  35 + """
  36 + attachment = Attachment()
  37 + cursor = self.attachment_cursor(empty_cursor)
  38 + attachment_dict = self.dictfetchall(cursor)
  39 + for line in attachment_dict:
  40 + attachment.description = line['description']
  41 + attachment.id = line['id']
  42 + attachment.filename = line['filename']
  43 + attachment.title = attachment.filename
  44 + attachment.size = line['size']
  45 + attachment.author = line['author']
  46 + attachment.used_by = line['type']
  47 + attachment.ipnr = line['ipnr']
  48 + attachment.url = attachment.used_by + "/" + attachment.id \
  49 + + "/" + attachment.filename
  50 + attachment.created = self.get_attachment_created(cursor,
  51 + line['id'])
  52 + if match("\.(\w+)$", attachment.filename):
  53 + attachment.mimetype = attachment.filename.lower()
  54 + attachment.save()
  55 +
  56 + def fetch_data_revision(self, empty_cursor):
  57 + """ This method is responsible for seeking the revision data in
  58 +        trac database and transfer them to the colab database.
  59 +
  60 +        :param empty_cursor: A cursor coming from connectinos, it is necessary
  61 +       import the connections library from django.db, with it we can run
  62 +         sql commands.
  63 +
  64 +        :returns: Return is an revision object with your saved data
  65 +         in the colab database.
  66 +
  67 + """
  68 + revision = Revision()
  69 + cursor = self.revision_cursor(empty_cursor)
  70 + revision_dict = self.dictfetchall(cursor)
  71 + cursor = self.repository_cursor(empty_cursor)
  72 + repository_dict = self.dictfetchall(cursor)
  73 + for line in revision_dict:
  74 + revision.author = line['author']
  75 + revision.rev = line['rev']
  76 + revision.message = line['message']
  77 + revision.description = revision.message
  78 + revision.created = self.get_revision_created(cursor, line['rev'])
  79 + revision.repository_name = line['repos']
  80 + revision.save()
  81 +
  82 + def fetch_data_ticket(self, empty_cursor):
  83 + """ This method is responsible for seeking the ticket data in
  84 +        trac database and transfer them to the colab database.
  85 +
  86 +        :param empty_cursor: A cursor coming from connectinos, it is necessary
  87 +         import the connections library from django.db, with it we can run
  88 +         sql commands.
  89 +
  90 +        :returns: Return is an ticker object with your saved data
  91 +         in the colab database.
  92 +
  93 + """
  94 + ticket = Ticket()
  95 + collaborators = []
  96 + cursor = self.ticket_cursor(empty_cursor)
  97 + ticket_dict = self.dictfetchall(cursor)
  98 + for line in ticket_dict:
  99 + ticket.id = line['id']
  100 + ticket.summary = line['summary']
  101 + ticket.description_ticket = line['description']
  102 + ticket.milestone = line['milestone']
  103 + ticket.priority = line['priority']
  104 + ticket.component = line['component']
  105 + ticket.version = line['version']
  106 + ticket.severity = line['severity']
  107 + ticket.reporter = line['reporter']
  108 + ticket.status = line['status']
  109 + ticket.tag = ticket.status
  110 + if line['keywords']:
  111 + ticket.keywords = line['keywords']
  112 + if line['owner']:
  113 + ticket.owner = line['owner']
  114 + else:
  115 + ticket.owner = 'Anonymous'
  116 + if line['resolution']:
  117 + ticket.resolution = line['resolution']
  118 + else:
  119 + ticket.resolution = 'no resolution'
  120 + ticket.author = ticket.reporter
  121 + ticket.created = self.get_ticket_created(cursor, line['id'])
  122 + ticket.modified = self.get_ticket_modified(cursor, line['id'])
  123 + if line['reporter'] not in collaborators:
  124 + collaborators.append(line['reporter'])
  125 + ticket.collaborators = collaborators
  126 + ticket.update_user(ticket.author)
  127 + ticket.save()
  128 +
  129 + def fetch_data_wiki(self, empty_cursor):
  130 + """ This method is responsible for seeking the wiki data in
  131 +        trac database and transfer them to the colab database.
  132 +
  133 +        :param empty_cursor: A cursor coming from connectinos, it is necessary
  134 +         import the connections library from django.db, with it we can run
  135 +         sql commands.
  136 +
  137 +        :returns: Return is an wiki object with your saved data
  138 +         in the colab database.
  139 +
  140 + """
  141 + wiki = Wiki()
  142 + cursor = self.wiki_cursor(empty_cursor)
  143 + wiki_dict = self.dictfetchall(cursor)
  144 + collaborators = []
  145 + for line in wiki_dict:
  146 + wiki.update_user(line['author'])
  147 + wiki.title = line['name']
  148 + wiki.wiki_text = line['text']
  149 + wiki.author = line['author']
  150 + if line['author'] not in collaborators:
  151 + collaborators.append(line['author'])
  152 + wiki.collaborators = collaborators
  153 + wiki.created = self.get_wiki_created(cursor, line['name'])
  154 + wiki.modified = self.get_wiki_modified(cursor, line['name'])
  155 +
  156 + wiki.save()
  157 +
  158 + def dictfetchall(self, cursor):
  159 + """ This method is responsible for taking the cursor content
  160 +        and turn it into a dictionary.
  161 +
  162 +        The cursor returns an array of tuples, With this method it will return
  163 + a list of dictionaries..
  164 +
  165 +        :param cursor: A cursor coming from connections, it is necessary
  166 +         import the connections from library django.db, with it we can run
  167 +         sql commands.
  168 +
  169 +        :returns: Return are cursor.fetchall() in the format of dictionary
  170 +
  171 + """
  172 + desc = cursor.description
  173 + return [
  174 + dict(zip([col[0] for col in desc], row))
  175 + for row in cursor.fetchall()
  176 + ]
  177 +
  178 + def wiki_cursor(self, cursor):
  179 + """ This is the method in charge of getting the wiki table data and
  180 +        put them in the cursor.
  181 +
  182 +        :param cursor: A cursor coming from connections, it is necessary
  183 +         import the connections from library django.db, with it we can run
  184 +         sql commands.
  185 +
  186 +        :returns: The return is the result of the desired query
  187 +
  188 + """
  189 + cursor.execute('''SELECT * FROM wiki;''')
  190 + return cursor
  191 +
  192 + def attachment_cursor(self, cursor):
  193 + """ This is the method in charge of getting the attachment table data and
  194 +        put them in the cursor.
  195 +
  196 +        :param cursor: A cursor coming from connections, it is necessary
  197 +         import the connections from library django.db, with it we can run
  198 +         sql commands.
  199 +
  200 +        :returns: The return is the result of the desired query
  201 +
  202 + """
  203 + cursor.execute('''SELECT * FROM attachment;''')
  204 + return cursor
  205 +
  206 + def ticket_cursor(self, cursor):
  207 + """ This is the method in charge of getting the ticket table data and
  208 +        put them in the cursor.
  209 +
  210 +        :param cursor: A cursor coming from connections, it is necessary
  211 +         import the connections from library django.db, with it we can run
  212 +         sql commands.
  213 +
  214 +        :returns: The return is the result of the desired query
  215 +
  216 + """
  217 + cursor.execute('''SELECT * FROM ticket;''')
  218 + return cursor
  219 +
  220 + def revision_cursor(self, cursor):
  221 + """ This is the method in charge of getting the revision table data and
  222 +        put them in the cursor.
  223 +
  224 +        :param cursor: A cursor coming from connections, it is necessary
  225 +         import the connections from library django.db, with it we can run
  226 +         sql commands.
  227 +
  228 +        :returns: The return is the result of the desired query
  229 +
  230 + """
  231 + cursor.execute('''SELECT * FROM revision;''')
  232 + return cursor
  233 +
  234 + def repository_cursor(self, cursor):
  235 + """ This is the method in charge of getting the repository table data and
  236 +        put them in the cursor.
  237 +
  238 +        :param cursor: A cursor coming from connections, it is necessary
  239 +         import the connections from library django.db, with it we can run
  240 +         sql commands.
  241 +
  242 +        :returns: The return is the result of the desired query
  243 +
  244 + """
  245 + cursor.execute('''SELECT * FROM repository;''')
  246 + return cursor
  247 +
  248 + def get_wiki_modified(self, cursor, wiki_name):
  249 + """ This is the method in charge of getting the datetime in the wiki was
  250 +        modified and put it in GMT format.
  251 +
  252 +        :param cursor: A cursor coming from connections, it is necessary
  253 +         import the connections from library django.db, with it we can run
  254 +         sql commands.
  255 +
  256 +        :param wiki_name: is the name of the current wiki.
  257 +
  258 +        :returns: The return is the result of the desired query
  259 +
  260 + """
  261 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  262 + (MAX(wiki.time)/1000000) * INTERVAL '1s', \
  263 + name from wiki where(name=\'""" + wiki_name + """\') \
  264 + group by name; """)
  265 + matriz_data_wiki = cursor.fetchall()
  266 + modified_data = matriz_data_wiki[0][0]
  267 + return modified_data
  268 +
  269 + def get_wiki_created(self, cursor, wiki_name):
  270 + """ This is the method in charge of getting the datetime in the wiki was
  271 +        created and put it in GMT format.
  272 +
  273 +        :param cursor: A cursor coming from connections, it is necessary
  274 +         import the connections from library django.db, with it we can run
  275 +         sql commands.
  276 +
  277 +        :param wiki_name: is the name of the current wiki.
  278 +
  279 +        :returns: The return is the result of the desired query
  280 +
  281 + """
  282 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  283 + (MIN(wiki.time)/1000000) * INTERVAL '1s', \
  284 + name from wiki where(name=\'""" + wiki_name + """\') \
  285 + group by name; """)
  286 + matriz_data_wiki = cursor.fetchall()
  287 + modified_data = matriz_data_wiki[0][0]
  288 + return modified_data
  289 +
  290 + def get_attachment_created(self, cursor, attachment_id):
  291 + """ This is the method in charge of getting the datetime in the
  292 + attachment was created and put it in GMT format.
  293 +
  294 +        :param cursor: A cursor coming from connections, it is necessary
  295 +         import the connections from library django.db, with it we can run
  296 +         sql commands.
  297 +
  298 +        :param attachment_id: is the id of the current attachment.
  299 +
  300 +        :returns: The return is the result of the desired query
  301 +
  302 + """
  303 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  304 + (MIN(attachment.time)/1000000) * INTERVAL '1s', \
  305 + id from attachment \
  306 + where(id=\'""" + attachment_id + """\') \
  307 + group by id; """)
  308 + matriz_data_attachment = cursor.fetchall()
  309 + modified_data = matriz_data_attachment[0][0]
  310 + return modified_data
  311 +
  312 + def get_revision_created(self, cursor, revision):
  313 + """ This is the method in charge of getting the datetime in the revision
  314 + was modified and put it in GMT format.
  315 +
  316 +        :param cursor: A cursor coming from connections, it is necessary
  317 +         import the connections from library django.db, with it we can run
  318 +         sql commands.
  319 +
  320 +        :param revision: is the current revision.
  321 +
  322 +        :returns: The return is the result of the desired query
  323 +
  324 + """
  325 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  326 + (MIN(revision.time)/1000000) * INTERVAL '1s', \
  327 + rev from revision where(rev=\'""" + revision + """\') \
  328 + group by rev; """)
  329 + matriz_data_revision = cursor.fetchall()
  330 + modified_data = matriz_data_revision[0][0]
  331 + return modified_data
  332 +
  333 + def get_ticket_created(self, cursor, ticket_id):
  334 + """ This is the method in charge of getting the datetime in the ticket
  335 + was created and put it in GMT format.
  336 +
  337 +        :param cursor: A cursor coming from connections, it is necessary
  338 +         import the connections from library django.db, with it we can run
  339 +         sql commands.
  340 +
  341 +        :param ticket_id: is the id of the current ticket.
  342 +
  343 +        :returns: The return is the result of the desired query
  344 +
  345 + """
  346 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  347 + (MIN(ticket.time)/1000000) * INTERVAL '1s', \
  348 + id from ticket where(id=""" + str(ticket_id) + """) \
  349 + group by id; """)
  350 + matriz_data_ticket = cursor.fetchall()
  351 + modified_data = matriz_data_ticket[0][0]
  352 + return modified_data
  353 +
  354 + def get_ticket_modified(self, cursor, ticket_id):
  355 + """ This is the method in charge of getting the datetime in the ticket
  356 + was modified and put it in GMT format.
  357 +
  358 +        :param cursor: A cursor coming from connections, it is necessary
  359 +         import the connections from library django.db, with it we can run
  360 +         sql commands.
  361 +
  362 +        :param ticket_id: is the id of the current ticket.
  363 +
  364 +        :returns: The return is the result of the desired query
  365 + """
  366 + cursor.execute("""SELECT TIMESTAMP WITH TIME ZONE 'epoch' + \
  367 + (MAX(ticket.time)/1000000) * INTERVAL '1s', \
  368 + id from ticket where(id=""" + str(ticket_id) + """) \
  369 + group by id; """)
  370 + matriz_data_ticket = cursor.fetchall()
  371 + modified_data = matriz_data_ticket[0][0]
  372 + return modified_data
colab/proxy/trac/fixtures/__init__.py
colab/proxy/trac/fixtures/trac_data.json
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +[{"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.058Z", "user": null}, "model": "trac.wiki", "pk": "CamelCase"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.010Z", "user": null}, "model": "trac.wiki", "pk": "InterMapTxt"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.023Z", "user": null}, "model": "trac.wiki", "pk": "InterTrac"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.017Z", "user": null}, "model": "trac.wiki", "pk": "InterWiki"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.040Z", "user": null}, "model": "trac.wiki", "pk": "PageTemplates"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.122Z", "user": null}, "model": "trac.wiki", "pk": "RecentChanges"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.061Z", "user": null}, "model": "trac.wiki", "pk": "SandBox"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.033Z", "user": null}, "model": "trac.wiki", "pk": "TitleIndex"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.142Z", "user": null}, "model": "trac.wiki", "pk": "TracAccessibility"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.174Z", "user": null}, "model": "trac.wiki", "pk": "TracAdmin"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.206Z", "user": null}, "model": "trac.wiki", "pk": "TracBackup"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.030Z", "user": null}, "model": "trac.wiki", "pk": "TracBatchModify"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.097Z", "user": null}, "model": "trac.wiki", "pk": "TracBrowser"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.050Z", "user": null}, "model": "trac.wiki", "pk": "TracCgi"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.177Z", "user": null}, "model": "trac.wiki", "pk": "TracChangeset"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.046Z", "user": null}, "model": "trac.wiki", "pk": "TracEnvironment"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.196Z", "user": null}, "model": "trac.wiki", "pk": "TracFastCgi"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.190Z", "user": null}, "model": "trac.wiki", "pk": "TracFineGrainedPermissions"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.116Z", "user": null}, "model": "trac.wiki", "pk": "TracGuide"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.100Z", "user": null}, "model": "trac.wiki", "pk": "TracImport"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.180Z", "user": null}, "model": "trac.wiki", "pk": "TracIni"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.087Z", "user": null}, "model": "trac.wiki", "pk": "TracInstall"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.037Z", "user": null}, "model": "trac.wiki", "pk": "TracInterfaceCustomization"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.139Z", "user": null}, "model": "trac.wiki", "pk": "TracLinks"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.020Z", "user": null}, "model": "trac.wiki", "pk": "TracLogging"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.126Z", "user": null}, "model": "trac.wiki", "pk": "TracModPython"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.135Z", "user": null}, "model": "trac.wiki", "pk": "TracModWSGI"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.027Z", "user": null}, "model": "trac.wiki", "pk": "TracNavigation"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.145Z", "user": null}, "model": "trac.wiki", "pk": "TracNotification"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.170Z", "user": null}, "model": "trac.wiki", "pk": "TracPermissions"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.164Z", "user": null}, "model": "trac.wiki", "pk": "TracPlugins"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.119Z", "user": null}, "model": "trac.wiki", "pk": "TracQuery"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.129Z", "user": null}, "model": "trac.wiki", "pk": "TracReports"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.084Z", "user": null}, "model": "trac.wiki", "pk": "TracRepositoryAdmin"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.158Z", "user": null}, "model": "trac.wiki", "pk": "TracRevisionLog"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.183Z", "user": null}, "model": "trac.wiki", "pk": "TracRoadmap"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.154Z", "user": null}, "model": "trac.wiki", "pk": "TracRss"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.067Z", "user": null}, "model": "trac.wiki", "pk": "TracSearch"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.064Z", "user": null}, "model": "trac.wiki", "pk": "TracStandalone"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.151Z", "user": null}, "model": "trac.wiki", "pk": "TracSupport"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.076Z", "user": null}, "model": "trac.wiki", "pk": "TracSyntaxColoring"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.113Z", "user": null}, "model": "trac.wiki", "pk": "TracTickets"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.203Z", "user": null}, "model": "trac.wiki", "pk": "TracTicketsCustomFields"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.071Z", "user": null}, "model": "trac.wiki", "pk": "TracTimeline"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:22Z", "modified": "2015-02-11T16:13:15.054Z", "user": null}, "model": "trac.wiki", "pk": "TracUnicode"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.193Z", "user": null}, "model": "trac.wiki", "pk": "TracUpgrade"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.132Z", "user": null}, "model": "trac.wiki", "pk": "TracWiki"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.080Z", "user": null}, "model": "trac.wiki", "pk": "TracWorkflow"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.110Z", "user": null}, "model": "trac.wiki", "pk": "WikiDeletePage"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.167Z", "user": null}, "model": "trac.wiki", "pk": "WikiFormatting"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.200Z", "user": null}, "model": "trac.wiki", "pk": "WikiHtml"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.107Z", "user": null}, "model": "trac.wiki", "pk": "WikiMacros"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.103Z", "user": null}, "model": "trac.wiki", "pk": "WikiNewPage"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.161Z", "user": null}, "model": "trac.wiki", "pk": "WikiPageNames"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.090Z", "user": null}, "model": "trac.wiki", "pk": "WikiProcessors"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.187Z", "user": null}, "model": "trac.wiki", "pk": "WikiRestructuredText"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.094Z", "user": null}, "model": "trac.wiki", "pk": "WikiRestructuredTextLinks"}, {"fields": {"collaborators": "[u'trac']", "author": "trac", "wiki_text": "", "created": "2015-02-09T19:57:23Z", "modified": "2015-02-11T16:13:15.148Z", "user": null}, "model": "trac.wiki", "pk": "WikiStart"}]
0 \ No newline at end of file 2 \ No newline at end of file
colab/proxy/trac/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals 2 from __future__ import unicode_literals
3 3
4 -from django.db import models, migrations, connections  
5 -  
6 -  
7 -def create_views(apps, schema_editor):  
8 - connection = connections['trac']  
9 -  
10 - cursor = connection.cursor()  
11 -  
12 - # revision_view  
13 - cursor.execute('''  
14 - CREATE OR REPLACE VIEW revision_view AS SELECT  
15 - revision.rev,  
16 - revision.author,  
17 - revision.message,  
18 - repository.value AS repository_name,  
19 - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,  
20 - CONCAT(revision.repos, '-', revision.rev) AS key  
21 - FROM revision  
22 - INNER JOIN repository ON(  
23 - repository.id = revision.repos  
24 - AND repository.name = 'name'  
25 - AND repository.value != ''  
26 - );  
27 - ''')  
28 -  
29 - # attachment_view  
30 - cursor.execute('''  
31 - CREATE OR REPLACE VIEW attachment_view AS SELECT  
32 - CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,  
33 - attachment.type AS used_by,  
34 - attachment.filename AS filename,  
35 - attachment.id as attach_id,  
36 - (SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,  
37 - attachment.author AS author,  
38 - attachment.description AS description,  
39 - attachment.size AS size,  
40 - TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created  
41 - FROM attachment;  
42 - ''')  
43 -  
44 - # wiki_view  
45 - cursor.execute('''  
46 - CREATE OR REPLACE VIEW wiki_view AS SELECT  
47 - wiki.name AS name,  
48 - (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name  
49 - AND wiki2.version = MAX(wiki.version)) AS wiki_text,  
50 - (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name  
51 - AND wiki3.version = 1) AS author,  
52 - string_agg(DISTINCT wiki.author, ', ') AS collaborators,  
53 - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,  
54 - TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,  
55 - (SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name  
56 - AND wiki4.version = MAX(wiki.version)) AS modified_by  
57 - FROM wiki  
58 - GROUP BY wiki.name;  
59 - ''')  
60 -  
61 - # ticket_view  
62 - cursor.execute('''  
63 - CREATE OR REPLACE VIEW ticket_view AS SELECT  
64 - ticket.id AS id,  
65 - ticket.summary as summary,  
66 - ticket.description as description,  
67 - ticket.milestone as milestone,  
68 - ticket.priority as priority,  
69 - ticket.component as component,  
70 - ticket.version as version,  
71 - ticket.severity as severity,  
72 - ticket.reporter as reporter,  
73 - ticket.reporter as author,  
74 - ticket.status as status,  
75 - ticket.keywords as keywords,  
76 - (SELECT  
77 - string_agg(DISTINCT ticket_change.author, ', ')  
78 - FROM ticket_change WHERE ticket_change.ticket = ticket.id  
79 - GROUP BY ticket_change.ticket) as collaborators,  
80 - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,  
81 - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,  
82 - (SELECT  
83 - ticket_change.author  
84 - FROM ticket_change  
85 - WHERE ticket_change.ticket = ticket.id  
86 - AND ticket_change.time = ticket.changetime  
87 - LIMIT 1  
88 - ) AS modified_by  
89 - FROM ticket;  
90 - ''')  
91 -  
92 - # ticket_collab_count_view  
93 - cursor.execute('''  
94 - CREATE OR REPLACE VIEW ticket_collab_count_view AS  
95 - SELECT  
96 - COALESCE (t1.author, t2.author) as author,  
97 - (COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count  
98 - FROM  
99 - (SELECT author, count(*) as count  
100 - FROM ticket_change  
101 - GROUP BY author  
102 - ORDER BY author  
103 - ) AS t1  
104 - FULL OUTER JOIN  
105 - (SELECT reporter as author, count(*) as count  
106 - FROM ticket  
107 - GROUP BY reporter  
108 - ORDER BY reporter  
109 - ) AS t2  
110 - ON t1.author = t2.author;  
111 - ''')  
112 -  
113 - # wiki_collab_count_view  
114 - cursor.execute('''  
115 - CREATE OR REPLACE VIEW wiki_collab_count_view AS  
116 - SELECT author, count(*) from wiki GROUP BY author;  
117 - ''')  
118 -  
119 -  
120 -def drop_views(apps, schema_editor):  
121 - connection = connections['trac']  
122 -  
123 - cursor = connection.cursor()  
124 - cursor.execute('''  
125 - DROP VIEW IF EXISTS revision_view;  
126 - DROP VIEW IF EXISTS ticket_view;  
127 - DROP VIEW IF EXISTS wiki_view;  
128 - DROP VIEW IF EXISTS ticket_collab_count_view;  
129 - DROP VIEW IF EXISTS wiki_collab_count_view;  
130 - DROP VIEW IF EXISTS attachment_view;  
131 - ''') 4 +from django.db import models, migrations
  5 +import django.db.models.deletion
  6 +import hitcounter.models
  7 +from django.conf import settings
132 8
133 9
134 class Migration(migrations.Migration): 10 class Migration(migrations.Migration):
135 11
136 dependencies = [ 12 dependencies = [
  13 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
137 ] 14 ]
138 15
139 operations = [ 16 operations = [
140 - migrations.RunPython(code=create_views, reverse_code=drop_views) 17 + migrations.CreateModel(
  18 + name='Attachment',
  19 + fields=[
  20 + ('url', models.TextField(serialize=False, primary_key=True)),
  21 + ('attach_id', models.TextField()),
  22 + ('used_by', models.TextField()),
  23 + ('filename', models.TextField()),
  24 + ('author', models.TextField(blank=True)),
  25 + ('title', models.TextField(blank=True)),
  26 + ('description', models.TextField(blank=True)),
  27 + ('modified', models.DateTimeField(blank=True)),
  28 + ('mimetype', models.TextField(blank=True)),
  29 + ('size', models.IntegerField(blank=True)),
  30 + ('ipnr', models.TextField(blank=True)),
  31 + ],
  32 + options={
  33 + 'verbose_name': 'Attachment',
  34 + 'verbose_name_plural': 'Attachment',
  35 + },
  36 + bases=(models.Model, hitcounter.models.HitCounterModelMixin),
  37 + ),
  38 + migrations.CreateModel(
  39 + name='Revision',
  40 + fields=[
  41 + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
  42 + ('rev', models.TextField(blank=True)),
  43 + ('author', models.TextField(blank=True)),
  44 + ('message', models.TextField(blank=True)),
  45 + ('description', models.TextField(blank=True)),
  46 + ('repository_name', models.TextField(blank=True)),
  47 + ('created', models.DateTimeField(null=True, blank=True)),
  48 + ('modified', models.DateTimeField(null=True, blank=True)),
  49 + ],
  50 + options={
  51 + 'verbose_name': 'Revision',
  52 + 'verbose_name_plural': 'Revision',
  53 + },
  54 + bases=(models.Model, hitcounter.models.HitCounterModelMixin),
  55 + ),
  56 + migrations.CreateModel(
  57 + name='Ticket',
  58 + fields=[
  59 + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
  60 + ('summary', models.TextField(blank=True)),
  61 + ('description_ticket', models.TextField(blank=True)),
  62 + ('milestone', models.TextField(blank=True)),
  63 + ('priority', models.TextField(blank=True)),
  64 + ('component', models.TextField(blank=True)),
  65 + ('version', models.TextField(blank=True)),
  66 + ('severity', models.TextField(blank=True)),
  67 + ('reporter', models.TextField(blank=True)),
  68 + ('author', models.TextField(blank=True)),
  69 + ('status', models.TextField(blank=True)),
  70 + ('tag', models.TextField(blank=True)),
  71 + ('keywords', models.TextField(blank=True)),
  72 + ('collaborators', models.TextField(blank=True)),
  73 + ('created', models.DateTimeField(null=True, blank=True)),
  74 + ('modified', models.DateTimeField(null=True, blank=True)),
  75 + ('modified_by', models.TextField(blank=True)),
  76 + ('owner', models.TextField(blank=True)),
  77 + ('resolution', models.TextField(blank=True)),
  78 + ],
  79 + options={
  80 + 'verbose_name': 'Ticket',
  81 + 'verbose_name_plural': 'Ticket',
  82 + },
  83 + bases=(models.Model, hitcounter.models.HitCounterModelMixin),
  84 + ),
  85 + migrations.CreateModel(
  86 + name='Wiki',
  87 + fields=[
  88 + ('title', models.TextField(serialize=False, primary_key=True)),
  89 + ('wiki_text', models.TextField(blank=True)),
  90 + ('author', models.TextField(blank=True)),
  91 + ('collaborators', models.TextField(blank=True)),
  92 + ('created', models.DateTimeField(null=True, blank=True)),
  93 + ('modified', models.DateTimeField(null=True, blank=True)),
  94 + ('comment', models.TextField(blank=True)),
  95 + ('user', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, null=True)),
  96 + ],
  97 + options={
  98 + 'verbose_name': 'Wiki',
  99 + 'verbose_name_plural': 'Wiki',
  100 + },
  101 + bases=(models.Model, hitcounter.models.HitCounterModelMixin),
  102 + ),
141 ] 103 ]
colab/proxy/trac/models.py
@@ -7,23 +7,29 @@ from django.conf import settings @@ -7,23 +7,29 @@ from django.conf import settings
7 7
8 from hitcounter.models import HitCounterModelMixin 8 from hitcounter.models import HitCounterModelMixin
9 9
  10 +from colab.proxy.utils.models import Collaboration
10 from colab.accounts.models import User 11 from colab.accounts.models import User
  12 +from django.utils.translation import ugettext_lazy as _
11 13
12 14
13 class Attachment(models.Model, HitCounterModelMixin): 15 class Attachment(models.Model, HitCounterModelMixin):
  16 + type = 'attachment'
  17 + icon_name = 'file'
14 url = models.TextField(primary_key=True) 18 url = models.TextField(primary_key=True)
15 attach_id = models.TextField() 19 attach_id = models.TextField()
16 used_by = models.TextField() 20 used_by = models.TextField()
17 filename = models.TextField() 21 filename = models.TextField()
18 author = models.TextField(blank=True) 22 author = models.TextField(blank=True)
  23 + title = models.TextField(blank=True)
19 description = models.TextField(blank=True) 24 description = models.TextField(blank=True)
20 created = models.DateTimeField(blank=True) 25 created = models.DateTimeField(blank=True)
21 mimetype = models.TextField(blank=True) 26 mimetype = models.TextField(blank=True)
22 size = models.IntegerField(blank=True) 27 size = models.IntegerField(blank=True)
  28 + ipnr = models.TextField(blank=True)
23 29
24 class Meta: 30 class Meta:
25 - managed = False  
26 - db_table = 'attachment_view' 31 + verbose_name = _('Attachment')
  32 + verbose_name_plural = _('Attachment')
27 33
28 @property 34 @property
29 def filepath(self): 35 def filepath(self):
@@ -43,18 +49,23 @@ class Attachment(models.Model, HitCounterModelMixin): @@ -43,18 +49,23 @@ class Attachment(models.Model, HitCounterModelMixin):
43 except User.DoesNotExist: 49 except User.DoesNotExist:
44 return None 50 return None
45 51
46 -  
47 class Revision(models.Model, HitCounterModelMixin): 52 class Revision(models.Model, HitCounterModelMixin):
48 - key = models.TextField(blank=True, primary_key=True) 53 + update_field = 'created'
  54 + icon_name = 'align-right'
49 rev = models.TextField(blank=True) 55 rev = models.TextField(blank=True)
50 author = models.TextField(blank=True) 56 author = models.TextField(blank=True)
51 message = models.TextField(blank=True) 57 message = models.TextField(blank=True)
  58 + description = models.TextField(blank=True)
52 repository_name = models.TextField(blank=True) 59 repository_name = models.TextField(blank=True)
53 created = models.DateTimeField(blank=True, null=True) 60 created = models.DateTimeField(blank=True, null=True)
54 61
  62 + @property
  63 + def title(self):
  64 + return u'{} [{}]'.format(self.repository_name, self.rev)
  65 +
55 class Meta: 66 class Meta:
56 - managed = False  
57 - db_table = 'revision_view' 67 + verbose_name = _('Revision')
  68 + verbose_name_plural = _('Revision')
58 69
59 def get_absolute_url(self): 70 def get_absolute_url(self):
60 return u'/changeset/{}/{}'.format(self.rev, self.repository_name) 71 return u'/changeset/{}/{}'.format(self.rev, self.repository_name)
@@ -66,10 +77,11 @@ class Revision(models.Model, HitCounterModelMixin): @@ -66,10 +77,11 @@ class Revision(models.Model, HitCounterModelMixin):
66 return None 77 return None
67 78
68 79
69 -class Ticket(models.Model, HitCounterModelMixin):  
70 - id = models.IntegerField(primary_key=True) 80 +class Ticket(Collaboration, HitCounterModelMixin):
  81 + icon_name = 'tag'
  82 + type = 'ticket'
71 summary = models.TextField(blank=True) 83 summary = models.TextField(blank=True)
72 - description = models.TextField(blank=True) 84 + description_ticket = models.TextField(blank=True)
73 milestone = models.TextField(blank=True) 85 milestone = models.TextField(blank=True)
74 priority = models.TextField(blank=True) 86 priority = models.TextField(blank=True)
75 component = models.TextField(blank=True) 87 component = models.TextField(blank=True)
@@ -78,15 +90,28 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -78,15 +90,28 @@ class Ticket(models.Model, HitCounterModelMixin):
78 reporter = models.TextField(blank=True) 90 reporter = models.TextField(blank=True)
79 author = models.TextField(blank=True) 91 author = models.TextField(blank=True)
80 status = models.TextField(blank=True) 92 status = models.TextField(blank=True)
  93 + tag = models.TextField(blank=True)
81 keywords = models.TextField(blank=True) 94 keywords = models.TextField(blank=True)
82 collaborators = models.TextField(blank=True) 95 collaborators = models.TextField(blank=True)
83 created = models.DateTimeField(blank=True, null=True) 96 created = models.DateTimeField(blank=True, null=True)
84 modified = models.DateTimeField(blank=True, null=True) 97 modified = models.DateTimeField(blank=True, null=True)
85 - modified_by = models.TextField(blank=True) 98 + owner = models.TextField(blank=True)
  99 + resolution = models.TextField(blank=True)
  100 +
  101 + @property
  102 + def title(self):
  103 + return u'#{} - {}'.format(self.id, self.summary)
  104 +
  105 + @property
  106 + def description(self):
  107 + return u'{}\n{}\n{}\n{}\n{}\n{}\n{}'.format(
  108 + self.description_ticket, self.milestone, self.component,
  109 + self.severity, self.reporter, self.keywords, self.collaborators
  110 + )
86 111
87 class Meta: 112 class Meta:
88 - managed = False  
89 - db_table = 'ticket_view' 113 + verbose_name = _('Ticket')
  114 + verbose_name_plural = _('Ticket')
90 115
91 def get_absolute_url(self): 116 def get_absolute_url(self):
92 return u'/ticket/{}'.format(self.id) 117 return u'/ticket/{}'.format(self.id)
@@ -104,21 +129,26 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -104,21 +129,26 @@ class Ticket(models.Model, HitCounterModelMixin):
104 return None 129 return None
105 130
106 131
107 -class Wiki(models.Model, HitCounterModelMixin):  
108 - name = models.TextField(primary_key=True) 132 +class Wiki(Collaboration, HitCounterModelMixin):
  133 + type = "wiki"
  134 + icon_name = "book"
  135 + title = models.TextField(primary_key=True)
109 wiki_text = models.TextField(blank=True) 136 wiki_text = models.TextField(blank=True)
110 author = models.TextField(blank=True) 137 author = models.TextField(blank=True)
111 collaborators = models.TextField(blank=True) 138 collaborators = models.TextField(blank=True)
112 created = models.DateTimeField(blank=True, null=True) 139 created = models.DateTimeField(blank=True, null=True)
113 modified = models.DateTimeField(blank=True, null=True) 140 modified = models.DateTimeField(blank=True, null=True)
114 - modified_by = models.TextField(blank=True) 141 +
  142 + @property
  143 + def description(self):
  144 + return u'{}\n{}'.format(self.wiki_text, self.collaborators)
115 145
116 class Meta: 146 class Meta:
117 - managed = False  
118 - db_table = 'wiki_view' 147 + verbose_name = _('Wiki')
  148 + verbose_name_plural = _('Wiki')
119 149
120 def get_absolute_url(self): 150 def get_absolute_url(self):
121 - return u'/wiki/{}'.format(self.name) 151 + return u'/wiki/{}'.format(self.title)
122 152
123 def get_author(self): 153 def get_author(self):
124 try: 154 try:
@@ -128,6 +158,6 @@ class Wiki(models.Model, HitCounterModelMixin): @@ -128,6 +158,6 @@ class Wiki(models.Model, HitCounterModelMixin):
128 158
129 def get_modified_by(self): 159 def get_modified_by(self):
130 try: 160 try:
131 - return User.objects.get(username=self.modified_by) 161 + return User.objects.get(username=self.author)
132 except User.DoesNotExist: 162 except User.DoesNotExist:
133 return None 163 return None
colab/proxy/trac/search_indexes.py
@@ -75,7 +75,7 @@ class AttachmentIndex(BaseIndex, indexes.Indexable): @@ -75,7 +75,7 @@ class AttachmentIndex(BaseIndex, indexes.Indexable):
75 75
76 76
77 class WikiIndex(BaseIndex, indexes.Indexable): 77 class WikiIndex(BaseIndex, indexes.Indexable):
78 - title = indexes.CharField(model_attr='name') 78 + title = indexes.CharField(model_attr='title')
79 collaborators = indexes.CharField( 79 collaborators = indexes.CharField(
80 model_attr='collaborators', 80 model_attr='collaborators',
81 null=True, 81 null=True,
colab/proxy/trac/templates/search/indexes/trac/attachment_text.txt
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +{{ object.filename }}
  2 +{{ object.filename|slugify }}
  3 +{{ object.description }}
  4 +{{ object.description|slugify }}
  5 +{{ object.used_by }}
  6 +{{ object.mimetype }}
  7 +{{ object.get_author.get_full_name }}
  8 +
  9 +{% for k, v in extracted.metadata.items %}
  10 + {% for val in v %}
  11 + {{ k }}: {{ val|safe }}
  12 + {% endfor %}
  13 +{% endfor %}
  14 +
  15 +{{ extracted.contents|striptags|safe }}
colab/proxy/trac/templates/search/indexes/trac/revision_text.txt
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +{{ object.repository_name }}
  2 +{{ object.repository_name|slugify }}
  3 +{{ object.rev }}
  4 +{{ object.rev|slugify }}
  5 +{% firstof object.get_author.get_full_name object.author %}
  6 +{% firstof object.get_author.get_full_name|slugify object.author|slugify %}
  7 +{{ object.message }}
  8 +{{ object.message|slugify }}
colab/proxy/trac/templates/search/indexes/trac/ticket_text.txt
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +{{ object.summary }}
  2 +{{ object.summary|slugify }}
  3 +{{ object.description }}
  4 +{{ object.description|slugify }}
  5 +{{ object.milestone }}
  6 +{{ object.milestone|slugify }}
  7 +{{ object.component|slugify }}
  8 +{{ object.version }}
  9 +{{ object.severity }}
  10 +{{ object.severity|slugify }}
  11 +{{ object.reporter }}
  12 +{{ object.reporter|slugify }}
  13 +{% firstof object.get_author.get_fullname or object.author %}
  14 +{% firstof object.get_author.get_fullname|slugify or object.author|slugify %}
  15 +{{ object.status }}
  16 +{{ object.status|slugify }}
  17 +{{ object.keywords }}
  18 +{{ object.keywords|slugify }}
  19 +{{ object.collaborators }}
  20 +{{ object.collaborators|slugify }}
colab/proxy/trac/templates/search/indexes/trac/wiki_text.txt
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +{{ object.author }}
  2 +{{ object.get_author.get_full_name }}
  3 +{{ object.get_author.get_full_name|slugify }}
  4 +{{ object.name }}
  5 +{{ object.name|slugify }}
  6 +{{ object.collaborators }}
  7 +{{ object.collaborators|slugify }}
  8 +{{ object.wiki_text }}
  9 +{{ object.wiki_text|slugify }}
colab/proxy/trac/tests/__init__.py
colab/proxy/trac/tests/test_data_api.py
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +"""
  2 +Test DataAPI class.
  3 +Objective: Test parameters and behavior.
  4 +"""
  5 +from colab.proxy.trac.data_api import TracDataAPI
  6 +
  7 +from django.db import connections
  8 +from django.test import TestCase
  9 +
  10 +
  11 +class TracDataAPITest(TestCase):
  12 +
  13 + fixtures = ["trac_data.json"]
  14 +
  15 + def setUp(self):
  16 + self.connection = connections['default']
  17 + self.cursor = self.connection.cursor()
  18 +
  19 + def tearDown(self):
  20 + self.connection.close()
  21 +
  22 + def test_dict_fetch_all(self):
  23 + trac_dict = TracDataAPI()
  24 + self.cursor.execute(''' SELECT * FROM trac_wiki;''')
  25 + dict_result = trac_dict.dictfetchall(self.cursor)
  26 + self.assertIn('collaborators', dict_result[0])
  27 +
  28 + def test_dict_fetch_all_is_dict(self):
  29 + trac_dict = TracDataAPI()
  30 + self.cursor.execute(''' SELECT * FROM trac_wiki;''')
  31 + dict_result = trac_dict.dictfetchall(self.cursor)
  32 + self.assertIsInstance(dict_result[0], dict)
colab/proxy/trac/tests/test_trac.py
@@ -0,0 +1,205 @@ @@ -0,0 +1,205 @@
  1 +"""
  2 +Test Trac class.
  3 +Objective: Test parameters and behavior.
  4 +"""
  5 +from colab.accounts.models import User
  6 +from colab.proxy.trac.models import Attachment, Revision, Ticket, Wiki
  7 +from django.test import TestCase
  8 +
  9 +
  10 +class AttachmentTest(TestCase):
  11 +
  12 + def setUp(self):
  13 + self.attachment = self.create_attachment()
  14 +
  15 + def tearDown(self):
  16 + pass
  17 +
  18 + def create_attachment(self):
  19 + attachment = Attachment()
  20 + attachment.type = 'attachment'
  21 + attachment.icon_name = 'file'
  22 + attachment.url = 'example.com'
  23 + attachment.attach_id = 'attach_id'
  24 + attachment.used_by = 'used_by'
  25 + attachment.filename = 'filename'
  26 + attachment.author = 'author'
  27 + attachment.title = 'title'
  28 + attachment.description = 'description'
  29 + attachment.modified = '1994-11-05T08:15:30-05:00'
  30 + attachment.created = '1994-11-05T08:15:30-05:00'
  31 + attachment.mimetype = 'mimetype'
  32 + attachment.size = 20
  33 + attachment.save()
  34 +
  35 + return attachment
  36 +
  37 + def test_validade_filepath(self):
  38 + file_path = '/mnt/trac/attachments/used_by/attach_id/filename'
  39 + self.assertEqual(file_path, self.attachment.filepath)
  40 +
  41 + def test_validade_absolute_url(self):
  42 + absolute_url = u'/raw-attachment/example.com'
  43 + self.assertEqual(absolute_url, self.attachment.get_absolute_url())
  44 +
  45 + def test_validade_author(self):
  46 + author = 'author'
  47 + self.user = create_user()
  48 + self.assertEqual(author, str(self.attachment.get_author()))
  49 +
  50 + def test_invalidade_author(self):
  51 + self.assertEqual(None, self.attachment.get_author())
  52 +
  53 +
  54 +class RevisionTest(TestCase):
  55 + def setUp(self):
  56 + self.revision = self.create_revision()
  57 +
  58 + def create_revision(self):
  59 + revision = Revision()
  60 + revision.update_field = 'created'
  61 + revision.icon_name = 'align-right'
  62 + revision.rev = 'rev'
  63 + revision.author = 'author'
  64 + revision.message = 'message'
  65 + revision.description = 'description'
  66 + revision.repository_name = 'repository'
  67 + revision.created = '1994-11-05T08:15:30-05:00'
  68 + revision.modified = '1994-11-05T08:15:30-05:00'
  69 + revision.save()
  70 +
  71 + return revision
  72 +
  73 + def test_title(self):
  74 + title = 'repository [rev]'
  75 + self.assertEqual(title, self.revision.title)
  76 +
  77 + def test_get_absolute_url(self):
  78 + absolute_url = '/changeset/rev/repository'
  79 + self.assertEqual(absolute_url, self.revision.get_absolute_url())
  80 +
  81 + def test_get_author(self):
  82 + author = 'author'
  83 + self.user = create_user()
  84 + self.assertEqual(author, str(self.revision.get_author()))
  85 +
  86 + def test_invalid_get_author(self):
  87 + self.assertEqual(None, self.revision.get_author())
  88 +
  89 +
  90 +class TicketTest(TestCase):
  91 + def setUp(self):
  92 + self.ticket = self.create_ticket()
  93 +
  94 + def create_ticket(self):
  95 + ticket = Ticket()
  96 + ticket.icon_name = 'tag'
  97 + ticket.type = 'ticket'
  98 + ticket.id = 20
  99 + ticket.summary = 'summary'
  100 + ticket.description_ticket = 'description'
  101 + ticket.milestone = 'milestone'
  102 + ticket.priority = 'priority'
  103 + ticket.component = 'component'
  104 + ticket.version = 'version'
  105 + ticket.severity = 'severity'
  106 + ticket.reporter = 'reporter'
  107 + ticket.author = 'author'
  108 + ticket.status = 'status'
  109 + ticket.tag = 'tag'
  110 + ticket.keywords = 'keywords'
  111 + ticket.collaborators = 'collaborators'
  112 + ticket.created = '1994-11-05T08:15:30-05:00'
  113 + ticket.modified = '1994-11-05T08:15:30-05:00'
  114 + ticket.save()
  115 +
  116 + return ticket
  117 +
  118 + def test_title(self):
  119 + title = '#20 - summary'
  120 + self.assertEqual(title, self.ticket.title)
  121 +
  122 + def test_description(self):
  123 + description1 = u'description\nmilestone\ncomponent\nseverity'
  124 + description2 = '\nreporter\nkeywords\ncollaborators'
  125 + description_test = description1 + description2
  126 + self.assertEqual(description_test, self.ticket.description)
  127 +
  128 + def test_get_absolute_url(self):
  129 + absolute_url = '/ticket/20'
  130 + self.assertEqual(absolute_url, self.ticket.get_absolute_url())
  131 +
  132 + def test_get_author(self):
  133 + author = 'author'
  134 + self.user = create_user()
  135 + self.assertEqual(author, str(self.ticket.get_author()))
  136 +
  137 + def test_invalid_get_author(self):
  138 + author = None
  139 + self.assertEqual(author, self.ticket.get_author())
  140 +
  141 + def test_get_modified_by(self):
  142 + self.user = create_user()
  143 + get_modified_by = str(self.ticket.get_modified_by())
  144 + self.assertEqual(str(self.ticket.modified_by), get_modified_by)
  145 +
  146 + def test_invalid_get_modified_by(self):
  147 + get_modified_by = self.ticket.get_modified_by()
  148 + self.assertEqual(None, get_modified_by)
  149 +
  150 +
  151 +class WikiTest(TestCase):
  152 + def setUp(self):
  153 + self.wiki = self.create_wiki()
  154 +
  155 + def create_wiki(self):
  156 + wiki = Wiki()
  157 + wiki.type = "wiki"
  158 + wiki.icon_name = "book"
  159 + wiki.title = 'title'
  160 + wiki.wiki_text = 'wiki_text'
  161 + wiki.author = 'author'
  162 + wiki.collaborators = 'collaborators'
  163 + wiki.created = '1994-11-05T08:15:30-05:00'
  164 + wiki.modified = '1994-11-05T08:15:30-05:00'
  165 + wiki.save()
  166 +
  167 + return wiki
  168 +
  169 + def test_description(self):
  170 + description_test = u'wiki_text\ncollaborators'
  171 + self.assertEqual(description_test, self.wiki.description)
  172 +
  173 + def test_get_absolute_url(self):
  174 + absolute_url = u'/wiki/title'
  175 + self.assertEqual(absolute_url, self.wiki.get_absolute_url())
  176 +
  177 + def test_get_author(self):
  178 + author = 'author'
  179 + self.user = create_user()
  180 + self.assertEqual(author, str(self.wiki.get_author()))
  181 +
  182 + def test_invalid_get_author(self):
  183 + author = None
  184 + self.assertEqual(author, self.wiki.get_author())
  185 +
  186 + def test_get_modified_by(self):
  187 + self.user = create_user()
  188 + get_modified_by = str(self.wiki.get_modified_by())
  189 + modified_by = "author"
  190 + self.assertEqual(modified_by, get_modified_by)
  191 +
  192 + def test_invalid_get_modified_by(self):
  193 + get_modified_by = self.wiki.get_modified_by()
  194 + self.assertEqual(None, get_modified_by)
  195 +
  196 +
  197 +def create_user():
  198 + user = User()
  199 + user.username = "author"
  200 + user.first_name = "FisrtName"
  201 + user.last_name = "LastName"
  202 + user.modified_by = "author"
  203 + user.save()
  204 +
  205 + return user
docs/source/conf.py
@@ -18,7 +18,9 @@ import os @@ -18,7 +18,9 @@ import os
18 # If extensions (or modules to document with autodoc) are in another directory, 18 # If extensions (or modules to document with autodoc) are in another directory,
19 # add these directories to sys.path here. If the directory is relative to the 19 # add these directories to sys.path here. If the directory is relative to the
20 # documentation root, use os.path.abspath to make it absolute, like shown here. 20 # documentation root, use os.path.abspath to make it absolute, like shown here.
21 -#sys.path.insert(0, os.path.abspath('.')) 21 +sys.path.insert(0, os.path.abspath('../../colab/proxy'))
  22 +from django.conf import settings
  23 +settings.configure()
22 24
23 # -- General configuration ------------------------------------------------ 25 # -- General configuration ------------------------------------------------
24 26
docs/source/dev.rst
1 Developer Documentation 1 Developer Documentation
2 -================== 2 +=======================
3 3
4 Getting Started 4 Getting Started
5 --------------- 5 ---------------
docs/source/index.rst
@@ -30,6 +30,8 @@ Contents: @@ -30,6 +30,8 @@ Contents:
30 user 30 user
31 plugindev 31 plugindev
32 dev 32 dev
  33 + trac
  34 +
33 35
34 36
35 Indices and tables 37 Indices and tables
@@ -38,4 +40,3 @@ Indices and tables @@ -38,4 +40,3 @@ Indices and tables
38 * :ref:`genindex` 40 * :ref:`genindex`
39 * :ref:`modindex` 41 * :ref:`modindex`
40 * :ref:`search` 42 * :ref:`search`
41 -  
docs/source/plugindev.rst
1 Plugin Developer Documentation 1 Plugin Developer Documentation
2 -================== 2 +==============================
3 3
4 Getting Started 4 Getting Started
5 --------------- 5 ---------------
docs/source/trac.rst
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +trac package
  2 +============
  3 +
  4 +Submodules
  5 +----------
  6 +
  7 +trac.data_api module
  8 +--------------------
  9 +
  10 +.. automodule:: trac.data_api
  11 + :members:
  12 + :undoc-members:
  13 + :show-inheritance:
docs/source/user.rst
@@ -16,6 +16,72 @@ Plugins @@ -16,6 +16,72 @@ Plugins
16 ------- 16 -------
17 .. TODO 17 .. TODO
18 18
  19 +Trac
  20 +++++
  21 +
  22 +
  23 +Since Trac already installed:
  24 +
  25 +- Easily, you can install it as follows:
  26 +
  27 +.. code-block:: sh
  28 +
  29 + $ pip install trac
  30 +
  31 +To enable Trac plugin must first configure the trac database in /etc/colab/settings.yml:
  32 +
  33 +1. vim /etc/colab/settings.yaml
  34 +
  35 +.. code-block:: yaml
  36 +
  37 + DATABASES:
  38 + default:
  39 + ENGINE: django.db.backends.postgresql_psycopg2
  40 + HOST: localhost
  41 + NAME: colab
  42 + USER: colab
  43 + PASSWORD: colab
  44 + trac:
  45 + ENGINE: django.db.backends.postgresql_psycopg2
  46 + HOST: localhost
  47 + NAME: trac
  48 + USER: colab
  49 + PASSWORD: colab
  50 +
  51 +- Yet this file uncomment in PROXIED_APPS the Trac:
  52 +
  53 +.. code-block:: yaml
  54 +
  55 + PROXIED_APPS:
  56 + # gitlab:
  57 + # upstream: 'http://localhost:8090/gitlab/'
  58 + # private_token: ''
  59 + trac:
  60 + upstream: 'http://localhost:5000/trac/'
  61 +
  62 +- Create the database in postgresql with user
  63 +
  64 +.. code-block:: sh
  65 +
  66 + $ sudo -u postgres psql
  67 + $ create database trac owner colab;
  68 +
  69 +- Now, generate the migrations:
  70 +
  71 +.. code-block:: sh
  72 +
  73 + # Since you are in the folder colab
  74 + $ workon colab
  75 + $ colab-admin makemigrations
  76 + $ colab-admin migrate trac
  77 +
  78 +- Finally, just import the Trac data (may take a few minutes):
  79 +
  80 +.. code-block:: sh
  81 +
  82 + # Since you are in the folder colab
  83 + $ colab-admin import_proxy_data
  84 +
19 Settings 85 Settings
20 -------- 86 --------
21 87
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages @@ -3,7 +3,7 @@ from setuptools import setup, find_packages
3 3
4 4
5 REQUIREMENTS = [ 5 REQUIREMENTS = [
6 - 'Django==1.7.5', 6 + 'Django==1.7.7',
7 'psycopg2==2.5.1', 7 'psycopg2==2.5.1',
8 'django-piston==0.2.3', 8 'django-piston==0.2.3',
9 'pytz==2011n', 9 'pytz==2011n',
@@ -6,7 +6,6 @@ import sys @@ -6,7 +6,6 @@ import sys
6 os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings' 6 os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings'
7 os.environ['COLAB_SETTINGS'] = 'tests/settings.yaml' 7 os.environ['COLAB_SETTINGS'] = 'tests/settings.yaml'
8 os.environ['COVERAGE_PROCESS_START'] = '.coveragerc' 8 os.environ['COVERAGE_PROCESS_START'] = '.coveragerc'
9 -os.environ['REUSE_DB'] = '0'  
10 9
11 import django 10 import django
12 import coverage 11 import coverage
@@ -14,7 +13,6 @@ import coverage @@ -14,7 +13,6 @@ import coverage
14 from django.test.utils import get_runner 13 from django.test.utils import get_runner
15 from django.conf import settings 14 from django.conf import settings
16 15
17 -  
18 def runtests(): 16 def runtests():
19 if django.VERSION >= (1, 7, 0): 17 if django.VERSION >= (1, 7, 0):
20 django.setup() 18 django.setup()
tests/settings.yaml
@@ -64,10 +64,10 @@ ROBOTS_NOINDEX: false @@ -64,10 +64,10 @@ ROBOTS_NOINDEX: false
64 64
65 ### Colab proxied apps 65 ### Colab proxied apps
66 PROXIED_APPS: 66 PROXIED_APPS:
67 - gitlab:  
68 - upstream: 'http://localhost:8090/gitlab/'  
69 - private_token: ''  
70 -# trac:  
71 -# upstream: 'http://localhost:5000/trac/' 67 +# gitlab:
  68 +# upstream: 'http://localhost:8090/gitlab/'
  69 +# private_token: ''
  70 + trac:
  71 + upstream: 'http://localhost:5000/trac/'
72 72
73 73
vagrant/centos.sh
@@ -19,7 +19,7 @@ fi @@ -19,7 +19,7 @@ fi
19 19
20 yum -y groupinstall "Development tools" 20 yum -y groupinstall "Development tools"
21 21
22 -yum install -y git unzip mercurial libev-devel gettext libxml2-devel libxslt-devel openssl-devel libffi-devel libjpeg-turbo-devel zlib-devel freetype-devel postgresql-devel python-devel postgresql-server 22 +yum install -y git unzip mercurial libev-devel gettext libxml2-devel libxslt-devel openssl-devel libffi-devel libjpeg-turbo-devel zlib-devel freetype-devel postgresql-devel python-devel postgresql-server java
23 23
24 ### Install Virtualenvwrapper 24 ### Install Virtualenvwrapper
25 which pip2.7 > /dev/null || 25 which pip2.7 > /dev/null ||
vagrant/misc/etc/init.d/solr
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +#!/bin/bash
  2 +# chkconfig: 2345 95 20
  3 +# description: Solr
  4 +# processname: myscript
  5 +#
  6 +#-----------------------------------------------------
  7 +# Script for running solr as a service.
  8 +#
  9 +# Usage: service solr {start|stop|restart|status}"
  10 +#
  11 +#-----------------------------------------------------
  12 +# This should be placed in /etc/init.d
  13 +
  14 +. /etc/rc.d/init.d/functions
  15 +
  16 +# Path to pid file
  17 +PIDFILE=/var/run/solr.pid
  18 +
  19 +# Service name
  20 +NAME="Solr"
  21 +
  22 +# Service description
  23 +DESC="start/stop Solr Server"
  24 +
  25 +SOLR_INIT="/home/vagrant/solr-4.10.3/start.sh"
  26 +
  27 +case $1 in
  28 + start)
  29 + action "Starting ${NAME}: " daemon --pidfile $PIDFILE $SOLR_INIT
  30 + ;;
  31 + stop)
  32 + action "Stopping ${NAME}: " killproc -p $PIDFILE
  33 + ;;
  34 + restart)
  35 + $0 stop
  36 + $0 start
  37 + ;;
  38 + status)
  39 + status -p $PIDFILE solr
  40 + ;;
  41 + *)
  42 + echo "Usage: $0 {start|stop|restart|status}"
  43 + exit 3
  44 + ;;
  45 +esac
vagrant/provision.sh
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 set -x 3 set -x
4 4
  5 +### Configure Colab
5 export VIRTUALENVWRAPPER_PYTHON="/usr/bin/python2.7" 6 export VIRTUALENVWRAPPER_PYTHON="/usr/bin/python2.7"
6 7
7 set +e 8 set +e
@@ -32,3 +33,22 @@ fi @@ -32,3 +33,22 @@ fi
32 33
33 colab-admin migrate 34 colab-admin migrate
34 colab-admin loaddata /vagrant/tests/test_data.json 35 colab-admin loaddata /vagrant/tests/test_data.json
  36 +
  37 +
  38 +### Install solr
  39 +
  40 +colab-admin build_solr_schema -f /tmp/schema.xml
  41 +
  42 +export SOLR_VERSION=4.10.3
  43 +export SOLR_CONFS="/tmp/schema.xml"
  44 +
  45 +$basedir/ci/install_solr.sh
  46 +/home/vagrant/solr-4.10.3/bin/solr stop -p 8983
  47 +
  48 +# Init.d Solr files
  49 +sudo cp $basedir/vagrant/misc/etc/init.d/solr /etc/init.d/
  50 +cp $basedir/vagrant/solr/start.sh /home/vagrant/solr-$SOLR_VERSION
  51 +sudo chkconfig --add solr
  52 +sudo service solr start
  53 +
  54 +colab-admin rebuild_index --noinput
vagrant/solr/start.sh
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +#!/bin/bash
  2 +
  3 +# Directory where solr is installed
  4 +SOLR_HOME=/home/vagrant/solr-4.10.3/example
  5 +
  6 +# Java options for Solr
  7 +OPTIONS="-Xmx128m"
  8 +
  9 +# Path to pid file
  10 +PIDFILE=/var/run/solr.pid
  11 +
  12 +# Path to log file
  13 +LOG_FILE=/var/log/solr.log
  14 +
  15 +COMMAND="java $OPTIONS -jar start.jar"
  16 +
  17 +cd $SOLR_HOME
  18 +nohup $COMMAND > $LOG_FILE 2>&1 &
  19 +echo $! > $PIDFILE
  20 +exit $?
vagrant/ubuntu.sh
@@ -5,7 +5,7 @@ set -ex @@ -5,7 +5,7 @@ set -ex
5 ### Install dependencies 5 ### Install dependencies
6 apt-get update 6 apt-get update
7 7
8 -apt-get install curl git unzip mercurial build-essential libev-dev gettext libxml2-dev libxslt1-dev libssl-dev libffi-dev libjpeg-dev zlib1g-dev libfreetype6-dev libpq-dev python-dev postgresql virtualenvwrapper python-pip -y 8 +apt-get install curl git unzip mercurial build-essential libev-dev gettext libxml2-dev libxslt1-dev libssl-dev libffi-dev libjpeg-dev zlib1g-dev libfreetype6-dev libpq-dev python-dev postgresql virtualenvwrapper python-pip java-common -y
9 9
10 10
11 ### Create conf directory 11 ### Create conf directory