User:Alsroot/trash/Object Bundles: Difference between revisions

 
(23 intermediate revisions by 5 users not shown)
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 ''[Entry]'' section
* bundles will be installed as a composite object i.e. as a directory of packaged to the bundle files<br>''METADATA'' should contain ''[Entry]'' 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 ''[Entry]'' presents) this section defines Journal entry to represent composite object, otherwise Journal entry for ''[Metadata]/entry'' 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 51: Line 49:
| ''entry''
| ''entry''
| mandatory
| mandatory
| if bundle is composite, ''entry'' 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
| define metadata for final Journal entry
|-
|-
| ''uid''
| ''uid''
Line 66: 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.
 
==== [Entry] section ====
 
If this section exists bundle will be installed as a 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
|-
| ''exec''
| optional
| how to activate Journal entry, overrides ''[Metadata]'' fields(like ''activity'' and ''mime_type'') of ''[Metadata]/entry'' file
|-
|}
 
=== MANIFEST file ===
 
File which contains a new-line-terminated list of file names inside bundle.


== Benefit to Sugar ==
== Benefit to Sugar ==
Line 107: Line 85:
* make Browse upload object bundles when the server says so
* make Browse upload object bundles when the server says so
* 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
* 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 ==
Line 116: Line 181:
# Resume it from Journal
# Resume it from Journal


How to test composite object:
How to test composite object (unfortunately [http://dev.sugarlabs.org/ticket/1101 #1101] prevents uploading bundles with library to wiki):
# Download any .xol bundle
# Download any .xol bundle
# Activate it(it should be opened in Browse)
# Activate it(it should be opened in Browse)
Line 136: 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 145: 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]]