@@ -842,9 +842,7 @@ fn run_core(
842842 . collect :: < Result < _ > > ( ) ?;
843843 let exercises_details = client. get_exercises_details ( exercises) ?;
844844
845- let tmc_config = TmcConfig :: load ( client_name) ?;
846-
847- let projects_dir = tmc_config. projects_dir ;
845+ let projects_dir = TmcConfig :: load ( client_name) ?. projects_dir ;
848846 let mut projects_config = ProjectsConfig :: load ( & projects_dir) ?;
849847
850848 let mut course_data = HashMap :: < String , Vec < ( String , String ) > > :: new ( ) ;
@@ -1519,6 +1517,53 @@ fn run_settings(
15191517 } ) ;
15201518 print_output ( & output, pretty, warnings)
15211519 }
1520+ ( "migrate" , Some ( matches) ) => {
1521+ let exercise_path = matches. value_of ( "exercise-path" ) . unwrap ( ) ;
1522+ let exercise_path = Path :: new ( exercise_path) ;
1523+
1524+ let course_slug = matches. value_of ( "course-slug" ) . unwrap ( ) ;
1525+
1526+ let exercise_slug = matches. value_of ( "exercise-slug" ) . unwrap ( ) ;
1527+
1528+ let exercise_checksum = matches. value_of ( "exercise-checksum" ) . unwrap ( ) ;
1529+
1530+ let mut projects_config = ProjectsConfig :: load ( & tmc_config. projects_dir ) ?;
1531+ let course_config = projects_config
1532+ . courses
1533+ . entry ( course_slug. to_string ( ) )
1534+ . or_insert ( CourseConfig {
1535+ course : course_slug. to_string ( ) ,
1536+ exercises : BTreeMap :: new ( ) ,
1537+ } ) ;
1538+
1539+ let target_dir = ProjectsConfig :: get_exercise_download_target (
1540+ & tmc_config. projects_dir ,
1541+ course_slug,
1542+ exercise_slug,
1543+ ) ;
1544+ if target_dir. exists ( ) {
1545+ anyhow:: bail!( "Tried to migrate exercise to {}; however, something already exists at that path." , target_dir. display( ) ) ;
1546+ }
1547+
1548+ course_config. exercises . insert (
1549+ exercise_slug. to_string ( ) ,
1550+ Exercise {
1551+ checksum : exercise_checksum. to_string ( ) ,
1552+ } ,
1553+ ) ;
1554+
1555+ move_dir ( exercise_path, & target_dir, pretty) ?;
1556+ course_config. save_to_projects_dir ( & tmc_config. projects_dir ) ?;
1557+
1558+ let output = Output :: < ( ) > :: OutputData ( OutputData {
1559+ status : Status :: Finished ,
1560+ result : OutputResult :: ExecutedCommand ,
1561+ message : Some ( "Migrated exercise" . to_string ( ) ) ,
1562+ percent_done : 1.0 ,
1563+ data : None ,
1564+ } ) ;
1565+ print_output ( & output, pretty, warnings)
1566+ }
15221567 ( "move-projects-dir" , Some ( matches) ) => {
15231568 let dir = matches. value_of ( "dir" ) . unwrap ( ) ;
15241569 let target = PathBuf :: from ( dir) ;
@@ -1547,84 +1592,10 @@ fn run_settings(
15471592 )
15481593 }
15491594
1550- let reporter = ProgressReporter :: new ( move |update| {
1551- let output = Output :: StatusUpdate :: < ( ) > ( update) ;
1552- print_output ( & output, pretty, & [ ] ) ?;
1553- Ok ( ( ) )
1554- } ) ;
1555-
1556- reporter
1557- . progress ( "Moving projects-dir" , 0.0 , None )
1558- . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1559-
15601595 let old_projects_dir = tmc_config. set_projects_dir ( target. clone ( ) ) ?;
1561- let mut file_count_copied = 0 ;
1562- let mut file_count_total = 0 ;
1563- for entry in WalkDir :: new ( & old_projects_dir) {
1564- let entry = entry. with_context ( || {
1565- format ! ( "Failed to read file inside {}" , old_projects_dir. display( ) )
1566- } ) ?;
1567- if entry. path ( ) . is_file ( ) {
1568- file_count_total += 1 ;
1569- }
1570- }
1571- for entry in WalkDir :: new ( & old_projects_dir) . contents_first ( true ) {
1572- let entry = entry. with_context ( || {
1573- format ! ( "Failed to read file inside {}" , old_projects_dir. display( ) )
1574- } ) ?;
1575- let entry_path = entry. path ( ) ;
1576-
1577- if entry_path. is_file ( ) {
1578- let relative = entry_path. strip_prefix ( & old_projects_dir) . unwrap ( ) ;
1579- let target_path = target. join ( relative) ;
1580- log:: debug!(
1581- "Moving {} -> {}" ,
1582- entry_path. display( ) ,
1583- target_path. display( )
1584- ) ;
1585-
1586- // create parent dir for target and copy it, remove source file after
1587- if let Some ( parent) = target_path. parent ( ) {
1588- fs:: create_dir_all ( parent) . with_context ( || {
1589- format ! ( "Failed to create directory at {}" , parent. display( ) )
1590- } ) ?;
1591- }
1592- fs:: copy ( entry_path, & target_path) . with_context ( || {
1593- format ! (
1594- "Failed to copy file from {} to {}" ,
1595- entry_path. display( ) ,
1596- target_path. display( )
1597- )
1598- } ) ?;
1599- fs:: remove_file ( entry_path) . with_context ( || {
1600- format ! (
1601- "Failed to remove file at {} after copying it" ,
1602- entry_path. display( )
1603- )
1604- } ) ?;
1605-
1606- file_count_copied += 1 ;
1607- reporter
1608- . progress (
1609- format ! ( "Moved file {} / {}" , file_count_copied, file_count_total) ,
1610- file_count_copied as f64 / file_count_total as f64 ,
1611- None ,
1612- )
1613- . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1614- } else if entry_path. is_dir ( ) {
1615- log:: debug!( "Deleting {}" , entry_path. display( ) ) ;
1616- fs:: remove_dir ( entry_path) . with_context ( || {
1617- format ! ( "Failed to remove directory at {}" , entry_path. display( ) )
1618- } ) ?;
1619- }
1620- }
1621-
1596+ move_dir ( & old_projects_dir, & target, pretty) ?;
16221597 tmc_config. save ( client_name) ?;
16231598
1624- reporter
1625- . finish_step ( "Finished moving project directory" , None )
1626- . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1627-
16281599 let output = Output :: < ( ) > :: OutputData ( OutputData {
16291600 status : Status :: Finished ,
16301601 result : OutputResult :: ExecutedCommand ,
@@ -1855,4 +1826,84 @@ fn json_to_toml(json: JsonValue) -> Result<TomlValue> {
18551826 }
18561827}
18571828
1829+ fn move_dir ( source : & Path , target : & Path , pretty : bool ) -> anyhow:: Result < ( ) > {
1830+ let reporter = ProgressReporter :: new ( move |update| {
1831+ let output = Output :: StatusUpdate :: < ( ) > ( update) ;
1832+ print_output ( & output, pretty, & [ ] ) ?;
1833+ Ok ( ( ) )
1834+ } ) ;
1835+
1836+ reporter
1837+ . progress (
1838+ format ! ( "Moving dir {} -> {}" , source. display( ) , target. display( ) ) ,
1839+ 0.0 ,
1840+ None ,
1841+ )
1842+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1843+
1844+ let mut file_count_copied = 0 ;
1845+ let mut file_count_total = 0 ;
1846+ for entry in WalkDir :: new ( source) {
1847+ let entry =
1848+ entry. with_context ( || format ! ( "Failed to read file inside {}" , source. display( ) ) ) ?;
1849+ if entry. path ( ) . is_file ( ) {
1850+ file_count_total += 1 ;
1851+ }
1852+ }
1853+ for entry in WalkDir :: new ( source) . contents_first ( true ) {
1854+ let entry =
1855+ entry. with_context ( || format ! ( "Failed to read file inside {}" , source. display( ) ) ) ?;
1856+ let entry_path = entry. path ( ) ;
1857+
1858+ if entry_path. is_file ( ) {
1859+ let relative = entry_path. strip_prefix ( source) . unwrap ( ) ;
1860+ let target_path = target. join ( relative) ;
1861+ log:: debug!(
1862+ "Moving {} -> {}" ,
1863+ entry_path. display( ) ,
1864+ target_path. display( )
1865+ ) ;
1866+
1867+ // create parent dir for target and copy it, remove source file after
1868+ if let Some ( parent) = target_path. parent ( ) {
1869+ fs:: create_dir_all ( parent) . with_context ( || {
1870+ format ! ( "Failed to create directory at {}" , parent. display( ) )
1871+ } ) ?;
1872+ }
1873+ fs:: copy ( entry_path, & target_path) . with_context ( || {
1874+ format ! (
1875+ "Failed to copy file from {} to {}" ,
1876+ entry_path. display( ) ,
1877+ target_path. display( )
1878+ )
1879+ } ) ?;
1880+ fs:: remove_file ( entry_path) . with_context ( || {
1881+ format ! (
1882+ "Failed to remove file at {} after copying it" ,
1883+ entry_path. display( )
1884+ )
1885+ } ) ?;
1886+
1887+ file_count_copied += 1 ;
1888+ reporter
1889+ . progress (
1890+ format ! ( "Moved file {} / {}" , file_count_copied, file_count_total) ,
1891+ file_count_copied as f64 / file_count_total as f64 ,
1892+ None ,
1893+ )
1894+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1895+ } else if entry_path. is_dir ( ) {
1896+ log:: debug!( "Deleting {}" , entry_path. display( ) ) ;
1897+ fs:: remove_dir ( entry_path) . with_context ( || {
1898+ format ! ( "Failed to remove directory at {}" , entry_path. display( ) )
1899+ } ) ?;
1900+ }
1901+ }
1902+
1903+ reporter
1904+ . finish_step ( "Finished moving project directory" , None )
1905+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
1906+ Ok ( ( ) )
1907+ }
1908+
18581909struct PrintToken ;
0 commit comments