Changes

m
Line 10: Line 10:  
* package Journal objects to bundles to preserve sugar related metadata
 
* package Journal objects to bundles to preserve sugar related metadata
 
* support composite Journal objects e.g. in case of library bundles instead of having .xol in Journal and unpacked files in ~/Library, all library files will be represented by one Journal entry, could be opened in Browse(''[Metadata]/mime_type'' should be text/html for that purpose) and could be transformed back to .xo on demand(e.g. for uploading library in Browse's pick-file field).
 
* support composite Journal objects e.g. in case of library bundles instead of having .xol in Journal and unpacked files in ~/Library, all library files will be represented by one Journal entry, could be opened in Browse(''[Metadata]/mime_type'' should be text/html for that purpose) and could be transformed back to .xo on demand(e.g. for uploading library in Browse's pick-file field).
 +
* Object Bundles exist only out of sugar (after uploading to the Journal .xo will be removed)
    
== Owner ==
 
== Owner ==
Line 18: Line 19:  
== Current status ==
 
== Current status ==
   −
* Targeted release: 0.86
+
* Targeted release:
* Last updated: Tue Jul 21 02:18:17 UTC 2009
+
* Last updated: Mon Jul 27 05:31:42 UTC 2009
* Percentage of completion: 0%
+
* Percentage of completion: 75%
    
== Detailed Description ==
 
== Detailed Description ==
Line 26: Line 27:  
This feature is a first approach to unified format for all types of bundles(in 0.86 it will support only Journal entries and new library bundles).
 
This feature is a first approach to unified format for all types of bundles(in 0.86 it will support only Journal entries and new library bundles).
   −
=== Bundle files hierarchy ===
+
Object bundle should have ''METADATA'' file in the top directory of .xo bundle.
   −
* ''MANIFEST'' EOL-terminalted list of files inside bundle
+
=== METADATA file ===
* ''METADATA'' file in [http://docs.python.org/library/configparser.html INI] format which describes bundle
     −
=== METADATA file ===
+
This file is in [http://docs.python.org/library/configparser.html INI] format which describes how to setup bundle.
   −
Object bundle can be installed to Journal in two forms:
+
Object bundle can be installed to Journal in two forms.
* files from bundle will be unpacked and installing as separate files, bundle itself will be removed(similar to .xoj)<br>''METADATA'' should not contain ''[Composite]'' section
  −
* bundles will be installed as a composite object i.e. as a directory of packaged to the bundle files<br>''METADATA'' should contain ''[Composite]'' section
     −
Any field in METADATA file can have ''_file'' suffix, in that case content of this field(substring w/o ''_file'' suffix) will be fetched from file inside of the bundle.
+
* '''Each file from bundle as separate Journal entry'''<br>files from bundle will be unpacked and installed as separate Journal entries, bundle itself will be removed(similar to .xoj)<br>final Journal entries can have ''activity'' field, so they are regular Journal entries that imported to Journal(w/o ''activity'' field) or created by activities(with ''activity'' field)<br>''METADATA'' should contain ''[Entry]'' sections for each Journal entry<br>if bundle has more then one entry, sections should be parted by different suffixes e.g. ''[Entry2]'', ''[Entry.additional]'' etc.
   −
==== [Metadata] section ====
+
* '''Composite Journal entry'''<br>bundle will be installed as a composite object i.e. as a directory of packaged to the bundle files that are represented by one Journal entry<br>final Journal entry can't have ''activity'' field<br>''METADATA'' should contain only one ''[Bundle]'' section
   −
This section is mandatory. It describes Datastore metadata fields of final entry in Journal. If bundle is composite(section ''[Composite]'' presents) this section defines Journal entry to represent composite object, otherwise Journal entry for ''[Metadata]/file'' file.
+
METADATA file can have one or several sections(depends on installation method) that describe metadata fields of final entry(ies) in Journal.
    
{| border=1 cellpadding=3 style="border: 1px solid white; border-collapse: collapse; background: #e3e4e5;"
 
{| border=1 cellpadding=3 style="border: 1px solid white; border-collapse: collapse; background: #e3e4e5;"
Line 49: Line 47:  
! Notes
 
! Notes
 
|-
 
|-
| ''file''
+
| ''entry''
 
| mandatory
 
| mandatory
| if bundle is composite, ''file' defines access point to composite object (e.g. index.html for library bundles); otherwise it defines file which will be installed to Journal
+
| if bundle is composite, ''entry'' defines access point to composite object (e.g. index.html for library bundles);<br>otherwise it defines file which will be installed to Journal
 
|-
 
|-
 
| ''mime_type''
 
| ''mime_type''
 
| mandatory
 
| mandatory
| define metadata for a file which will be stored in Journal, for composite objects it defines type of ''file'' file(e.g. text/html for libraries)
+
| define metadata for final Journal entry
 +
|-
 +
| ''uid''
 +
| ignored
 
|-
 
|-
 
| ''*''
 
| ''*''
Line 63: Line 64:  
|}
 
|}
   −
METADATA file could have several ''[Manifest]'' sections, in that case they should be parted by different suffixes e.g. ''[Manifest2]'', ''[Manifest.additional]'' etc. Multi-object bundles could be utilized in >0.86 for collections of objects or actions.
+
Any field in ''METADATA'' file can have ''_file'' suffix, in that case content of this field(substring w/o ''_file'' suffix) will be fetched from file inside of the bundle.
 
  −
==== [Composite] section ====
  −
 
  −
If this section exists bundle will be installed as composite object i.e. all bundle files will be represented by one Journal entry(could be useful in case of libraries).
  −
 
  −
{| border=1 cellpadding=3 style="border: 1px solid white; border-collapse: collapse; background: #e3e4e5;"
  −
|-style="background:#787878; color: white;"
  −
! Field
  −
! Flags
  −
! Notes
  −
|-
  −
|}
  −
 
  −
=== MANIFEST file ===
  −
 
  −
File which contains a new-line-terminated list of file names inside bundle.
      
== Benefit to Sugar ==
 
== Benefit to Sugar ==
Line 99: Line 84:  
** journal entries, former .xoj bundles (0.86)
 
** journal entries, former .xoj bundles (0.86)
 
* make Browse upload object bundles when the server says so
 
* make Browse upload object bundles when the server says so
* make Browse open bundles with libraries
+
* in an ideal implementation, composite feature should come from Datastore, but since DS has been extensively hacked in 0.86-0.88 cycles, for the first time, it could be a part of shell code
 +
 
 +
==== Implementation ====
 +
 
 +
* [http://git.sugarlabs.org/projects/sugar/repos/objectbundle sugar]
 +
* [http://git.sugarlabs.org/projects/sugar-toolkit/repos/objectbundle sugar-toolkit]
 +
* [http://git.sugarlabs.org/projects/browse/repos/objectbundle Browse]
 +
 
 +
Example of PHP code which could be used on server side to unpack object bundles to get metadata (like title, description, preview etc.)
 +
 
 +
require_once('Archive/Zip.php');
 +
 +
function rmtree($dir) {
 +
    $dir = "$dir";
 +
 +
    if ($dh = opendir($dir)) {
 +
        while (FALSE !== ($item = readdir($dh))) {
 +
            if ($item != '.' && $item != '..') {
 +
                $subdir = $dir . '/' . "$item";
 +
                if (is_dir($subdir))
 +
                    rmtree($subdir);
 +
                else
 +
                    unlink($subdir);
 +
            }
 +
        }
 +
        closedir($dh);
 +
        rmdir($dir);
 +
    }
 +
}
 +
 +
function unbundle($bundle) {
 +
    $zip = new Archive_Zip($bundle);
 +
 +
    $tmpdir = tempnam('/tmp', 'sugar');
 +
    if (file_exists($tmpdir))
 +
        unlink($tmpdir);
 +
    if (!mkdir($tmpdir)) {
 +
        return null;
 +
    }
 +
 +
    $out = $zip->extract(array('add_path' => $tmpdir, 'by_name' => array('METADATA')));
 +
    if (empty($out)) {
 +
        rmtree($tmpdir);
 +
        return null;
 +
    }
 +
 +
    $metadata = parse_ini_file($out[0]['filename'], true);
 +
    if (!$metadata) {
 +
        rmtree($tmpdir);
 +
        return null;
 +
    }
 +
 +
    $result = array();
 +
 +
    foreach ($metadata as $section => $items) {
 +
        if (!(substr($section, 0, 5) == 'Entry' || $section == 'Bundle'))
 +
            continue;
 +
        foreach ($items as $name => $value) {
 +
            if (substr($name, -5) == '_file') {
 +
                $name = substr($name, 0, -5);
 +
 +
                $out = $zip->extract(array('add_path' => $tmpdir, 'by_name' => array($value)));
 +
                if (empty($out)) {
 +
                    rmtree($tmpdir);
 +
                    return null;
 +
                }
 +
 +
                $value = file_get_contents($tmpdir.'/'.$value);
 +
            }
 +
            $result[$name] = $value;
 +
        }
 +
        break;
 +
    }
 +
 +
    rmtree($tmpdir);
 +
    return $result;
 +
}
 +
 +
// example usage of unbundle() function
 +
 +
$bundle = 'foo.xo';
 +
$metadata = unbundle($bundle);
 +
 +
if (!$metadata)
 +
    echo 'Can not open '.$bundle."\n";
 +
else
 +
    foreach ($metadata as $name => $value)
 +
        echo $name.'='.$value."\n";
    
== How To Test ==
 
== How To Test ==
    +
How to test non-composite objects:
 
# Create a new TurtleArt activity
 
# Create a new TurtleArt activity
 
# Upload the new entry to the SL wiki using Browse
 
# Upload the new entry to the SL wiki using Browse
 
# Use Browse to download the entry back to Journal
 
# Use Browse to download the entry back to Journal
 
# Resume it from Journal
 
# Resume it from Journal
 +
 +
How to test composite object (unfortunately [http://dev.sugarlabs.org/ticket/1101 #1101] prevents uploading bundles with library to wiki):
 +
# Download any .xol bundle
 +
# Activate it(it should be opened in Browse)
 +
# Upload Journal entry with library to SL wiki using Browse
 +
# Download .xo with library and open it
    
== User Experience ==
 
== User Experience ==
   −
Except that [http://wiki.laptop.org/go/Journal_entry_bundles .xoj] has:
+
We could have HTTP servers(see [[Features/Server Objects Sharing]]) that request .xo files, in that case Browse will provide object bundle for chosen(in ObjectChooser) Journal entry otherwise Browse will upload raw Journal entries.
* users can create object bundles outside of sugar(they do not have to follow JSON rules)
      
== Dependencies ==
 
== Dependencies ==
Line 123: Line 201:  
== Documentation ==
 
== Documentation ==
    +
* [http://www.mail-archive.com/sugar-devel@lists.sugarlabs.org/msg06874.html Email thread]
 
* [[Unified Bundles]]
 
* [[Unified Bundles]]
 +
* [[User:Alsroot/trash/Unified Objects | Unified Objects]]
 
* [http://wiki.laptop.org/go/Journal_entry_bundles Journal entry bundles]
 
* [http://wiki.laptop.org/go/Journal_entry_bundles Journal entry bundles]
 
* [http://wiki.laptop.org/go/Bundle_concepts Bundle concepts]
 
* [http://wiki.laptop.org/go/Bundle_concepts Bundle concepts]
 +
* [http://wiki.laptop.org/go/Manifest_Specification#Contents_Manifests MANIFEST specification]
    
== Release Notes ==
 
== Release Notes ==
Line 132: Line 213:  
== Comments and Discussion ==
 
== Comments and Discussion ==
 
* See [[{{TALKPAGENAME}}|discussion tab for this feature]] <!-- This adds a link to the "discussion" tab associated with your page.  This provides the ability to have ongoing comments or conversation without bogging down the main feature page -->
 
* See [[{{TALKPAGENAME}}|discussion tab for this feature]] <!-- This adds a link to the "discussion" tab associated with your page.  This provides the ability to have ongoing comments or conversation without bogging down the main feature page -->
  −
  −
[[Category:Feature Page Incomplete]]
  −
[[Category:Feature]]