{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-platform/pulls/comments/25179171","id":25179171,"diff_hunk":"@@ -345,6 +346,116 @@ def make_asset_id(course_id, asset_xml):\n         store.save_asset_metadata_list(all_assets, all_assets[0].edited_by, import_only=True)\n \n \n+def import_library_from_xml(\n+        store,\n+        user_id, data_dir, library_dirs,\n+        default_class='xmodule.raw_module.RawDescriptor',\n+        load_error_modules=True, static_content_store=None,\n+        target_library_id=None, display_name='',\n+        do_import_static=True, create_if_not_present=False\n+):\n+    \"\"\"\n+    Import xml-based libraries from data_dir into modulestore.\n+\n+    Returns:\n+        list of new libraries (should only contain one item, currently)\n+\n+    Args:\n+        store: a modulestore implementing ModuleStoreWriteBase in which to store the imported libraries.\n+\n+        data_dir: the root directory from which to find the xml courses.\n+\n+        library_dirs: If specified, the list of data_dir subdirectories to load. Otherwise, load\n+            all library dirs\n+\n+        target_library_id: is the LibraryKey that all modules should be remapped to\n+            after import off disk.\n+\n+        static_content_store: the static asset store\n+\n+        do_import_static: if True, then import the library's static files into static_content_store\n+            This can be employed for libraries which have substantial\n+            unchanging static content, which is too inefficient to import every\n+            time the course is loaded. Static content for some courses may also be\n+            served directly by nginx, instead of going through django.\n+\n+        create_if_not_present: If True, then a new library is created if it doesn't already exist.\n+            Otherwise, it throws an InvalidLocationError if the library does not exist.\n+\n+        default_class, load_error_modules: are arguments for constructing the XMLModuleStore (see its doc)\n+    \"\"\"\n+\n+    # We only actually support one library import at a time right now.\n+    if len(library_dirs) > 1:\n+        raise NotImplementedError(\n+            \"Only one library may be imported at a time from this function.\")\n+    lib_dir = path(data_dir) / library_dirs[0]\n+    lib_file = open(lib_dir / 'library.xml')\n+\n+    xml_module_store = XMLModuleStore(\n+        data_dir,\n+        default_class=default_class,\n+        course_dirs=library_dirs,\n+        load_error_modules=load_error_modules,\n+        xblock_mixins=store.xblock_mixins,\n+        xblock_select=store.xblock_select,\n+        library=True,\n+    )\n+\n+    try:\n+        library = store.get_library(target_library_id)\n+    except (ItemNotFoundError, AssertionError):\n+        library = None\n+    if library is None and create_if_not_present:\n+        library = store.create_library(\n+            org=target_library_id.org,\n+            library=target_library_id.library,\n+            user_id=user_id,\n+            fields={\"display_name\": display_name}\n+        )\n+\n+    logger, errors = make_error_tracker()  # pylint: disable=unused-variable\n+    system = ImportSystem(\n+        xml_module_store, library.location.library_key, lib_dir,\n+        logger,\n+        load_error_modules=load_error_modules,\n+        mixins=xml_module_store.xblock_mixins,\n+        field_data=KvsFieldData(kvs=DictKeyValueStore()))\n+\n+    # pylint: disable=no-member\n+    lib_data = etree.parse(lib_file, parser=edx_xml_parser).getroot()\n+\n+    # pylint: disable=no-member\n+    temp_library = system.process_xml(etree.tostring(lib_data, encoding='unicode'))\n+    # Return a list to make return signature similar to course import. Also to permit multi import in\n+    # the future if it's needed.\n+\n+    # Everything that has happened so far has only placed the data in a temporary position. We now move it\n+    # over to its destination library. First, delete the old items.\n+    for child in library.children:\n+        store.delete_item(child, user_id)\n+\n+    temp_key = temp_library.location.library_key\n+    library_key = library.location.library_key\n+    # Now stick all the new items into the library.\n+    for module in temp_library.children:\n+        _import_module_and_update_references(\n+            xml_module_store.get_item(module), store, user_id,\n+            temp_key,\n+            library_key,\n+            do_import_static=do_import_static,\n+            runtime=library.runtime,\n+            library=True\n+        )\n+\n+    if do_import_static:\n+        import_static_content(\n+            lib_dir, static_content_store,\n+            library_key, subpath='static', verbose=False)\n+\n+    return [library]","path":"common/lib/xmodule/xmodule/modulestore/xml_importer.py","position":169,"original_position":165,"commit_id":"b484342b1ab10748ed7748aea6b6b76475dd8510","original_commit_id":"d622bb240b562e7c998d29e210653e84b669b913","user":{"login":"Kelketek","id":1099483,"avatar_url":"https://avatars.githubusercontent.com/u/1099483?v=3","gravatar_id":"","url":"https://api.github.com/users/Kelketek","html_url":"https://github.com/Kelketek","followers_url":"https://api.github.com/users/Kelketek/followers","following_url":"https://api.github.com/users/Kelketek/following{/other_user}","gists_url":"https://api.github.com/users/Kelketek/gists{/gist_id}","starred_url":"https://api.github.com/users/Kelketek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kelketek/subscriptions","organizations_url":"https://api.github.com/users/Kelketek/orgs","repos_url":"https://api.github.com/users/Kelketek/repos","events_url":"https://api.github.com/users/Kelketek/events{/privacy}","received_events_url":"https://api.github.com/users/Kelketek/received_events","type":"User","site_admin":false},"body":"Alright. I'll see what I can do about this, then.","created_at":"2015-02-23T16:46:27Z","updated_at":"2015-02-23T16:46:27Z","html_url":"https://github.com/edx/edx-platform/pull/6846#discussion_r25179171","pull_request_url":"https://api.github.com/repos/edx/edx-platform/pulls/6846","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/comments/25179171"},"html":{"href":"https://github.com/edx/edx-platform/pull/6846#discussion_r25179171"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/6846"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-platform/pulls/6846","id":28394686,"html_url":"https://github.com/edx/edx-platform/pull/6846","diff_url":"https://github.com/edx/edx-platform/pull/6846.diff","patch_url":"https://github.com/edx/edx-platform/pull/6846.patch","issue_url":"https://api.github.com/repos/edx/edx-platform/issues/6846","number":6846,"state":"open","locked":false,"title":"Content Libraries Import/Export","user":{"login":"Kelketek","id":1099483,"avatar_url":"https://avatars.githubusercontent.com/u/1099483?v=3","gravatar_id":"","url":"https://api.github.com/users/Kelketek","html_url":"https://github.com/Kelketek","followers_url":"https://api.github.com/users/Kelketek/followers","following_url":"https://api.github.com/users/Kelketek/following{/other_user}","gists_url":"https://api.github.com/users/Kelketek/gists{/gist_id}","starred_url":"https://api.github.com/users/Kelketek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kelketek/subscriptions","organizations_url":"https://api.github.com/users/Kelketek/orgs","repos_url":"https://api.github.com/users/Kelketek/repos","events_url":"https://api.github.com/users/Kelketek/events{/privacy}","received_events_url":"https://api.github.com/users/Kelketek/received_events","type":"User","site_admin":false},"body":"**Background**: This PR implements import and export for content libraries, as well as for the Library Content Module.\r\n**Jira Ticket**: Implements [SOL-82](https://openedx.atlassian.net/browse/SOL-82)\r\n**Sandbox URLs**: http://content-libraries.sandbox.opencraft.com:18010/ (CMS) and http://content-libraries.sandbox.opencraft.com/ (LMS)\r\n**Partner information**: 3rd party-hosted open edX instance, for an edX solutions client.\r\n\r\n@bradenmacdonald Could you take a look at this? I'm especially interested in any advice you might have on how to effectively test it. We may need to contact the testing engineering team for additional advice there.","created_at":"2015-01-30T21:28:18Z","updated_at":"2015-02-23T16:46:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2effbf21dce229c12566b30bd073b08fdc90990d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-platform/pulls/6846/commits","review_comments_url":"https://api.github.com/repos/edx/edx-platform/pulls/6846/comments","review_comment_url":"https://api.github.com/repos/edx/edx-platform/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/edx-platform/issues/6846/comments","statuses_url":"https://api.github.com/repos/edx/edx-platform/statuses/b484342b1ab10748ed7748aea6b6b76475dd8510","head":{"label":"open-craft:content_libraries/import-export","ref":"content_libraries/import-export","sha":"b484342b1ab10748ed7748aea6b6b76475dd8510","user":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"repo":{"id":19940883,"name":"edx-platform","full_name":"open-craft/edx-platform","owner":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-craft/edx-platform","description":"the edX learning management system (LMS) and course authoring tool, Studio","fork":true,"url":"https://api.github.com/repos/open-craft/edx-platform","forks_url":"https://api.github.com/repos/open-craft/edx-platform/forks","keys_url":"https://api.github.com/repos/open-craft/edx-platform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-craft/edx-platform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-craft/edx-platform/teams","hooks_url":"https://api.github.com/repos/open-craft/edx-platform/hooks","issue_events_url":"https://api.github.com/repos/open-craft/edx-platform/issues/events{/number}","events_url":"https://api.github.com/repos/open-craft/edx-platform/events","assignees_url":"https://api.github.com/repos/open-craft/edx-platform/assignees{/user}","branches_url":"https://api.github.com/repos/open-craft/edx-platform/branches{/branch}","tags_url":"https://api.github.com/repos/open-craft/edx-platform/tags","blobs_url":"https://api.github.com/repos/open-craft/edx-platform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-craft/edx-platform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-craft/edx-platform/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-craft/edx-platform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-craft/edx-platform/statuses/{sha}","languages_url":"https://api.github.com/repos/open-craft/edx-platform/languages","stargazers_url":"https://api.github.com/repos/open-craft/edx-platform/stargazers","contributors_url":"https://api.github.com/repos/open-craft/edx-platform/contributors","subscribers_url":"https://api.github.com/repos/open-craft/edx-platform/subscribers","subscription_url":"https://api.github.com/repos/open-craft/edx-platform/subscription","commits_url":"https://api.github.com/repos/open-craft/edx-platform/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-craft/edx-platform/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-craft/edx-platform/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-craft/edx-platform/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-craft/edx-platform/contents/{+path}","compare_url":"https://api.github.com/repos/open-craft/edx-platform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-craft/edx-platform/merges","archive_url":"https://api.github.com/repos/open-craft/edx-platform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-craft/edx-platform/downloads","issues_url":"https://api.github.com/repos/open-craft/edx-platform/issues{/number}","pulls_url":"https://api.github.com/repos/open-craft/edx-platform/pulls{/number}","milestones_url":"https://api.github.com/repos/open-craft/edx-platform/milestones{/number}","notifications_url":"https://api.github.com/repos/open-craft/edx-platform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-craft/edx-platform/labels{/name}","releases_url":"https://api.github.com/repos/open-craft/edx-platform/releases{/id}","created_at":"2014-05-19T12:28:25Z","updated_at":"2014-12-10T07:44:28Z","pushed_at":"2015-02-20T23:25:46Z","git_url":"git://github.com/open-craft/edx-platform.git","ssh_url":"git@github.com:open-craft/edx-platform.git","clone_url":"https://github.com/open-craft/edx-platform.git","svn_url":"https://github.com/open-craft/edx-platform","homepage":"http://code.edx.org/","size":385671,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":1,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"1d5b2e2b273dbb945c6bf5e541d5f1c725ac906d","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":10391073,"name":"edx-platform","full_name":"edx/edx-platform","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-platform","description":"Open edX, the edX platform that powers http://edx.org","fork":false,"url":"https://api.github.com/repos/edx/edx-platform","forks_url":"https://api.github.com/repos/edx/edx-platform/forks","keys_url":"https://api.github.com/repos/edx/edx-platform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-platform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-platform/teams","hooks_url":"https://api.github.com/repos/edx/edx-platform/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-platform/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-platform/events","assignees_url":"https://api.github.com/repos/edx/edx-platform/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-platform/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-platform/tags","blobs_url":"https://api.github.com/repos/edx/edx-platform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-platform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-platform/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-platform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-platform/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-platform/languages","stargazers_url":"https://api.github.com/repos/edx/edx-platform/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-platform/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-platform/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-platform/subscription","commits_url":"https://api.github.com/repos/edx/edx-platform/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-platform/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-platform/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-platform/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-platform/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-platform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-platform/merges","archive_url":"https://api.github.com/repos/edx/edx-platform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-platform/downloads","issues_url":"https://api.github.com/repos/edx/edx-platform/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-platform/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-platform/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-platform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-platform/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-platform/releases{/id}","created_at":"2013-05-30T20:20:38Z","updated_at":"2015-02-23T16:40:33Z","pushed_at":"2015-02-23T16:41:13Z","git_url":"git://github.com/edx/edx-platform.git","ssh_url":"git@github.com:edx/edx-platform.git","clone_url":"https://github.com/edx/edx-platform.git","svn_url":"https://github.com/edx/edx-platform","homepage":"http://openedx.org/","size":1792630,"stargazers_count":1755,"watchers_count":1755,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":1006,"mirror_url":null,"open_issues_count":132,"forks":1006,"open_issues":132,"watchers":1755,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/6846"},"html":{"href":"https://github.com/edx/edx-platform/pull/6846"},"issue":{"href":"https://api.github.com/repos/edx/edx-platform/issues/6846"},"comments":{"href":"https://api.github.com/repos/edx/edx-platform/issues/6846/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/6846/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-platform/pulls/6846/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-platform/statuses/b484342b1ab10748ed7748aea6b6b76475dd8510"}}}}