1313from django .contrib .auth .models import User # pylint: disable=imported-auth-user
1414from django .utils import timezone
1515from django .utils .translation import gettext_lazy as _
16+ from opaque_keys .edx .locator import LibraryLocator , LibraryLocatorV2
1617
18+ from openedx .core .djangoapps .content_libraries .api import extract_library_v2_zip_to_dir
1719from xmodule .contentstore .django import contentstore
1820from xmodule .modulestore .django import modulestore
19- from xmodule .modulestore .xml_exporter import export_course_to_xml
21+ from xmodule .modulestore .xml_exporter import CourseLocator , export_course_to_xml , export_library_to_xml
2022
2123log = logging .getLogger (__name__ )
2224
@@ -66,10 +68,28 @@ def cmd_log(cmd, cwd):
6668 return output
6769
6870
69- def export_to_git (course_id , repo , user = '' , rdir = None ):
70- """Export a course to git."""
71+ def export_to_git (context_key , repo , user = '' , rdir = None ):
72+ """
73+ Export a course or library to git.
74+
75+ Args:
76+ context_key: LearningContextKey for the content to export
77+ repo (str): Git repository URL
78+ user (str): Optional username for git commit identity
79+ rdir (str): Optional custom directory name for the repository
80+
81+ Raises:
82+ GitExportError: For various git operation failures
83+ """
7184 # pylint: disable=too-many-statements
7285
86+ # Validate context_key type and determine export function and content type label
87+ if not isinstance (context_key , (LibraryLocatorV2 , LibraryLocator , CourseLocator )):
88+ raise TypeError (
89+ f"{ context_key !r} for git export must be LibraryLocatorV2, LibraryLocator, "
90+ f"or CourseLocator, not { type (context_key )} "
91+ )
92+
7393 if not GIT_REPO_EXPORT_DIR :
7494 raise GitExportError (GitExportError .NO_EXPORT_DIR )
7595
@@ -128,15 +148,31 @@ def export_to_git(course_id, repo, user='', rdir=None):
128148 log .exception ('Failed to pull git repository: %r' , ex .output )
129149 raise GitExportError (GitExportError .CANNOT_PULL ) from ex
130150
131- # export course as xml before commiting and pushing
151+ # export content as xml (or zip for v2 libraries) before commiting and pushing
132152 root_dir = os .path .dirname (rdirp )
133- course_dir = os .path .basename (rdirp ).rsplit ('.git' , 1 )[0 ]
153+ content_dir = os .path .basename (rdirp ).rsplit ('.git' , 1 )[0 ]
154+
155+ content_type_label = "course" if context_key .is_course else "library"
156+
157+ is_library_v2 = isinstance (context_key , LibraryLocatorV2 )
158+ if is_library_v2 :
159+ # V2 libraries use backup API with zip extraction
160+ content_export_func = extract_library_v2_zip_to_dir
161+ elif isinstance (context_key , LibraryLocator ):
162+ content_export_func = export_library_to_xml
163+ else :
164+ content_export_func = export_course_to_xml
165+
134166 try :
135- export_course_to_xml (modulestore (), contentstore (), course_id ,
136- root_dir , course_dir )
137- except (OSError , AttributeError ):
138- log .exception ('Failed export to xml' )
139- raise GitExportError (GitExportError .XML_EXPORT_FAIL ) # pylint: disable=raise-missing-from # noqa: B904
167+ if is_library_v2 :
168+ content_export_func (context_key , root_dir , content_dir , user )
169+ else :
170+ # V1 libraries and courses: use XML export (no user parameter)
171+ content_export_func (modulestore (), contentstore (), context_key ,
172+ root_dir , content_dir )
173+ except (OSError , AttributeError ) as ex :
174+ log .exception ('Failed to export %s' , content_type_label )
175+ raise GitExportError (GitExportError .XML_EXPORT_FAIL ) from ex
140176
141177 # Get current branch if not already set
142178 if not branch :
@@ -160,9 +196,7 @@ def export_to_git(course_id, repo, user='', rdir=None):
160196 ident = GIT_EXPORT_DEFAULT_IDENT
161197 time_stamp = timezone .now ()
162198 cwd = os .path .abspath (rdirp )
163- commit_msg = "Export from Studio at {time_stamp}" .format ( # noqa: UP032
164- time_stamp = time_stamp ,
165- )
199+ commit_msg = f"Export { content_type_label } from Studio at { time_stamp } "
166200 try :
167201 cmd_log (['git' , 'config' , 'user.email' , ident ['email' ]], cwd )
168202 cmd_log (['git' , 'config' , 'user.name' , ident ['name' ]], cwd )
@@ -180,3 +214,10 @@ def export_to_git(course_id, repo, user='', rdir=None):
180214 except subprocess .CalledProcessError as ex :
181215 log .exception ('Error running git push command: %r' , ex .output )
182216 raise GitExportError (GitExportError .CANNOT_PUSH ) from ex
217+
218+ log .info (
219+ '%s %s exported to git repository %s successfully' ,
220+ content_type_label .capitalize (),
221+ context_key ,
222+ repo ,
223+ )
0 commit comments