Ticket #21 (new enhancement)

Opened 3 years ago

Added support for nested directory levels

Reported by: MattJ Owned by: aje
Priority: minor Milestone:
Component: component1 Version:
Keywords: Cc:
Reproducibility: N/A

Description

We use trac to manage multiple projects and we organize our distrib area by project/version/build and only have the packages and their signatures within the build sub-directories. As out of the box tracdown only listed files within each project we added support for arbitrary depth of sub-directories.

Thought others might be interested in the modification...

Index: tracdown.py
===================================================================
--- tracdown.py	(revision 11)
+++ tracdown.py	(working copy)
@@ -14,6 +14,28 @@
     file_cs = """
 <?cs include "header.cs"?>
 <?cs include "rectang_menu_top.cs"?>
+
+<?cs def:cat_list(val, prefix) ?>
+   <?cs each:element = val.files ?>
+    <tr class="<?cs if:name(element) % #2 ?>even<?cs else ?>odd<?cs /if ?>">
+      <td class="name"<?cs if:element.padding ?> style="padding-left: <?cs var:element.padding ?>px"<?cs /if ?>
+      <?cs if:element.size == -2 ?>
+         colspan="3"><i><?cs var:element.name ?></i></td>
+      </tr>
+    <?cs elif:element.size == -1 ?>
+         colspan="3"><?cs var:prefix ?><a class="dir" href="<?cs var:element.url ?>"><?cs var:element.name ?></a></td>
+      </tr>
+      <?cs call:cat_list(element, prefix) ?>
+    <?cs else ?>
+         ><?cs var:prefix ?><a class="file" href="<?cs var:element.url ?>"><?cs var:element.name ?></a></td>
+         <td class="size"><?cs var:element.size ?></td>
+         <td class="age"><?cs var:element.time ?></td>
+      </tr>
+      <?cs call:cat_list(element, prefix) ?>
+    <?cs /if ?>
+   <?cs /each?>
+<?cs /def ?>
+
 <div id="ctxtnav" class="nav">
  <h2>Files Navigation</h2>
  <ul>
@@ -37,13 +59,7 @@
    </tr>
   </thead>
   <tbody>
-   <?cs each:file = category.files ?>
-    <tr class="<?cs if:name(file) % #2 ?>even<?cs else ?>odd<?cs /if ?>">
-     <td class="name"><a class="file" href="<?cs var:file.url ?>"><?cs var:file.name ?></a></td>
-     <td class="size"><?cs var:file.size ?></td>
-     <td class="age"><?cs var:file.time ?></td>
-    </tr>
-   <?cs /each?>
+    <?cs call:cat_list(category, "") ?>
   </tbody>
  </table>
 
@@ -65,62 +81,82 @@
         if match:
             return 1
 
-    def listcategories(self, root, sort, order=None):
+    def listcategories(self, req, directory, prefix, padding, sort, order=None, toplevel=False):
         files = []
-        names = os.listdir(root)
-        if (sort):
-            names.sort()
-            if (order == "rev" or order == "reverse"):
-                names.reverse()
+        directories = []
 
-        for file in names:
-            if os.path.isdir(os.path.join(root, file)):
-                files.append(file)
-        return files
-
-    def listfiles(self, root, category, sort, order=None):
-        files = []
-        names = os.listdir(os.path.join(root, category))
+        names = os.listdir(directory)
         if (sort):
             if (order == "age"):
                 names.sort(lambda x, y: os.path.getmtime(os.sep.join([root, category, x])) - os.path.getmtime(os.sep.join([root, category, y])))
                 names.reverse()
             else:
                 names.sort()
+            if (order == "rev" or order == "reverse"):
+                names.reverse()
 
-        for file in names:
-            files.append(file)
-        return files
 
+        for cat in names:
+            path = os.path.join(directory, cat)
+            if os.path.isdir(path):
+                url = "/downloads" + prefix + '/' + cat
+
+                if toplevel or len(req.path_info)>=len(url) and req.path_info[0:len(url)]==url :
+                    next_level = padding
+                    if not toplevel:
+                        next_level+=30
+
+                    subcategories = self.listcategories(req, path, prefix + '/' + cat, next_level, sort, order);
+                    directories.append({'name': cat,
+                                        'time': self.timestamp(path),
+                                        'url' : url,
+                                        'files': subcategories,
+                                        'padding' : padding,
+                                        'size': -1})
+                else:
+                    directories.append({'name': cat,
+                                        'time': self.timestamp(path),
+                                        'url' : url,
+                                        'padding' : padding,
+                                        'size': -1})
+            else:
+                url = self.config.get('download', 'url') + prefix + '/' + cat
+                files.append({'name': cat,
+                              'time': self.timestamp(path),
+                              'size': util.pretty_size(os.path.getsize(path)),
+                              'padding' : padding,
+                              'url': url})
+
+        if len(directories)==0 and len(files)==0:
+            directories.append({'name' : 'No released files',
+                                'padding' : padding,
+                                'size' : -2})
+
+        return directories + files
+
+
     def timestamp(self, path):
         thetime = os.path.getmtime(path)
         return time.strftime('%x %X', time.localtime(thetime))
 
+
+
     def process_request(self, req):
         req.hdf['title'] = self.config.get('download', 'title') or "Downloads"
         req.hdf['nightly'] = self.config.get('download', 'nightly') or "nightly"
         req.hdf['files.baseLink'] = self.env.href.cruisecontrol()
 
+        relpath = self.config.get('download','url')
+
+
         path = self.config.get('download', 'path') + '/'
-        baseurl = self.config.get('download', 'url') + '/'
         sort = self.config.get('download', 'sort') == 'true'
         catorder = self.config.get('download', 'category-order')
         order = self.config.get('download', 'file-order')
-        categories = self.listcategories(path, sort, order=catorder)
-        list = []
-        for category in categories:
-            files = []
-            for file in self.listfiles(path, category, sort, order=order):
-                url = baseurl + category + '/' + file
-                filename = os.path.join(path, category, file)
-                files.append({'name': file,
-                              'time': self.timestamp(filename),
-                              'size': util.pretty_size(os.path.getsize(filename)),
-                              'url': url})
-            list.append({'name': category,
-                         'time': self.timestamp(os.path.join(path, category)),
-                         'files': files})
-        req.hdf['files.categories'] = list
+
+        categories = self.listcategories(req, path, '', 0, sort, order=catorder, toplevel=True)
+
+        req.hdf['files.categories'] = categories
         template = req.hdf.parse(self.file_cs)
         add_stylesheet(req, 'common/css/browser.css')
         return template, None

Attachments

Add/Change #21 (Added support for nested directory levels)

Author


E-mail address and user name can be saved in the Preferences.


Change Properties
<Author field>
Action
as new
as The resolution will be set. Next status will be 'closed'
to The owner will change from aje. Next status will be 'new'
The owner will change from aje to anonymous. Next status will be 'assigned'
 
Note: See TracTickets for help on using tickets.