Line 8: |
Line 8: |
| == Summary == | | == Summary == |
| | | |
− | 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). |
| + | * Object Bundles exist only out of sugar (after uploading to the Journal .xo will be removed) |
| | | |
| == Owner == | | == Owner == |
Line 17: |
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 == |
| | | |
− | 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. |
| | | |
− | METADATA files could consists of several predefined sections:
| + | Object bundle can be installed to Journal in two forms. |
− | * ''[Metadata*]''
| |
− | * ''[Activity]'' (reserved for future use)
| |
− | * ''[Library]'' (reserved for future use)
| |
− | * ''[General]'' (reserved for future use)
| |
| | | |
− | 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.
| + | 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 50: |
Line 47: |
| ! Notes | | ! Notes |
| |- | | |- |
− | | ''journal_file'' | + | | ''entry'' |
− | | optional | + | | mandatory |
− | | if exists, this file will be unpacked while uploading bundle to Journal and current section defines its metadata<br>otherwise defines metadata for bundle itself and bundle will be stored as is in 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 |
− | |-
| |
− | | ''activity''
| |
− | | optional
| |
− | | bundle_id of activity to start Journal object(according to ''journal_file'') by default, if its absent then ''mime_type'' based action
| |
| |- | | |- |
| | ''mime_type'' | | | ''mime_type'' |
| | mandatory | | | mandatory |
− | | define metadata for a file which which will be stored in Journal(according to ''journal_file'') | + | | define metadata for final Journal entry |
| + | |- |
| + | | ''uid'' |
| + | | ignored |
| |- | | |- |
| | ''*'' | | | ''*'' |
| | optional | | | optional |
− | | any Datastore field, predefined or user defined | + | | any [[Features/Plain_Query_Format#System_terms|system]], [[Features/Plain_Query_Format#Users_predefined_terms|users predefined]] and arbitrary Datastore field |
| |- | | |- |
| |} | | |} |
| | | |
− | METADATA file could have several ''[Manifest]'' sections, in that case they would 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. |
| | | |
− | === MANIFEST file === | + | == Benefit to Sugar == |
− | | |
− | File which contains a new-line-terminated list of file names inside bundle.
| |
| | | |
− | == Benefit to Sugar ==
| + | This feature is a first approach to unified format for all types of bundles. |
| | | |
− | Let users export/import Journal objects.
| + | Current implementation is similar to [http://wiki.laptop.org/go/Journal_entry_bundles .xoj] bundles except that: |
| + | * it uses INI format instead of json(to make it more user-editing friendly) |
| + | * any field's value could fetched from file inside of the bundle |
| + | * supports multi-object bundles |
| | | |
| == Scope == | | == Scope == |
| | | |
− | <!--* deprecate .xol bundles-->
| + | * deprecate .xol bundles |
| * deprecate [http://wiki.laptop.org/go/Journal_entry_bundles .xoj] bundles | | * deprecate [http://wiki.laptop.org/go/Journal_entry_bundles .xoj] bundles |
| * provide unified format for metadata file in .xo bundles which should support | | * provide unified format for metadata file in .xo bundles which should support |
| ** activities, former .xo bundles (0.88) | | ** activities, former .xo bundles (0.88) |
− | ** libraries, former .xol bundles (0.88) | + | ** libraries, former .xol bundles (0.86) |
| ** 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 |
− | <!--* InfoSlicer generates object bundles in 0.86 environment-->
| + | * 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 == |
− | ''If this feature is noticeable by its target audience, how will their experiences change as a result? Describe what they will see or notice.''
| + | |
| + | 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. |
| | | |
| == Dependencies == | | == Dependencies == |
Line 109: |
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 118: |
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]]
| |