@@ -418,73 +418,28 @@ export default {
418418 const terminalBasePath = isAcodeTerminalPublicSafUri
419419 ? decodeURIComponent ( treeSegment . split ( "::" ) [ 0 ] || "" )
420420 : "" ;
421-
422- if ( isExternalStorageUri ) {
423- baseFolder = decodeURIComponent ( currentUri . split ( "%3A" ) [ 1 ] . split ( "/" ) [ 0 ] ) ;
424- } else if (
425- ! ( isExternalStorageUri || isTermuxUri || isAcodeTerminalPublicSafUri )
426- ) {
427- // Handle nested paths for regular file:// URIs
428- const pathParts = pathString . split ( "/" ) . filter ( Boolean ) ;
429- let currentPath = uri ;
430- let firstCreatedPath = null ;
431- let firstCreatedType = null ;
432-
433- for ( let i = 0 ; i < pathParts . length ; i ++ ) {
434- const isLastPart = i === pathParts . length - 1 ;
435- const partName = pathParts [ i ] ;
436- const newPath = Url . join ( currentPath , partName ) ;
437-
438- if ( isLastPart && isFile ) {
439- // Create file if it's the last part and we're creating a file
440- if ( ! ( await fsOperation ( newPath ) . exists ( ) ) ) {
441- await fsOperation ( currentPath ) . createFile ( partName ) ;
442- if ( firstCreatedPath === null ) {
443- firstCreatedPath = newPath ;
444- firstCreatedType = "file" ;
445- }
446- }
447- } else {
448- // Create directory for intermediate parts or when creating a folder
449- if ( ! ( await fsOperation ( newPath ) . exists ( ) ) ) {
450- await fsOperation ( currentPath ) . createDirectory ( partName ) ;
451- if ( firstCreatedPath === null ) {
452- firstCreatedPath = newPath ;
453- firstCreatedType = "folder" ;
454- }
455- }
456- }
457- currentPath = newPath ;
421+ const getTargetUri = ( baseUri , name , index ) => {
422+ if (
423+ ! ( isExternalStorageUri || isTermuxUri || isAcodeTerminalPublicSafUri )
424+ ) {
425+ return Url . join ( baseUri , name ) ;
458426 }
459427
460- return {
461- uri : firstCreatedPath || Url . join ( uri , pathParts [ 0 ] ) ,
462- type :
463- firstCreatedType ||
464- ( isFile && pathParts . length === 1 ? "file" : "folder" ) ,
465- } ;
466- }
467-
468- for ( let i = 0 ; i < parts . length ; i ++ ) {
469- const isLastElement = i === parts . length - 1 ;
470- const name = parts [ i ] ;
471- let fullUri = currentUri ;
472-
473- // Adjust URI for special cases
428+ let fullUri = baseUri ;
474429 if ( isExternalStorageUri ) {
475- if ( ! isSpecialCase && i === 0 ) {
430+ if ( ! isSpecialCase && index === 0 ) {
476431 fullUri += `::primary:${ baseFolder } /${ name } ` ;
477432 } else {
478433 fullUri += `/${ name } ` ;
479434 }
480435 } else if ( isTermuxUri ) {
481- if ( ! isSpecialCase && i === 0 ) {
436+ if ( ! isSpecialCase && index === 0 ) {
482437 fullUri += `::/data/data/com.termux/files/home/${ name } ` ;
483438 } else {
484439 fullUri += `/${ name } ` ;
485440 }
486441 } else if ( isAcodeTerminalPublicSafUri ) {
487- if ( ! isSpecialCase && i === 0 ) {
442+ if ( ! isSpecialCase && index === 0 ) {
488443 const sanitizedBase = terminalBasePath . endsWith ( "/" )
489444 ? `${ terminalBasePath } ${ name } `
490445 : `${ terminalBasePath } /${ name } ` ;
@@ -493,41 +448,79 @@ export default {
493448 fullUri += `/${ name } ` ;
494449 }
495450 }
496-
497- if ( isLastElement && isFile ) {
498- // Create file if it's the last element and isFile is true
499- if ( ! ( await fsOperation ( fullUri ) . exists ( ) ) ) {
500- await fsOperation ( currentUri ) . createFile ( name ) ;
501- } else {
502- return ;
503- }
504- } else {
505- // Create directory
506- if ( ! ( await fsOperation ( fullUri ) . exists ( ) ) ) {
507- await fsOperation ( currentUri ) . createDirectory ( name ) ;
508- } else {
509- return ;
451+ return fullUri ;
452+ } ;
453+ const getExpectedType = ( isLastPart ) =>
454+ isLastPart && isFile ? "file" : "folder" ;
455+ const ensureEntry = async ( baseUri , targetUri , name , expectedType ) => {
456+ const entries = await fsOperation ( baseUri ) . lsDir ( ) ;
457+ const existingEntry = entries . find ( ( entry ) => entry . name === name ) ;
458+
459+ if ( existingEntry ) {
460+ const actualType =
461+ existingEntry . isDirectory || existingEntry . isFile === false
462+ ? "folder"
463+ : "file" ;
464+ if ( actualType !== expectedType ) {
465+ throw new Error (
466+ `${ name } already exists as a ${ actualType } , expected ${ expectedType } .` ,
467+ ) ;
510468 }
469+
470+ return {
471+ url : existingEntry . url || targetUri ,
472+ created : false ,
473+ type : expectedType ,
474+ } ;
511475 }
512- currentUri = fullUri ;
476+
477+ const createdUrl =
478+ expectedType === "file"
479+ ? await fsOperation ( baseUri ) . createFile ( name )
480+ : await fsOperation ( baseUri ) . createDirectory ( name ) ;
481+
482+ return {
483+ url : createdUrl || targetUri ,
484+ created : true ,
485+ type : expectedType ,
486+ } ;
487+ } ;
488+ let firstCreatedPath = null ;
489+ let firstCreatedType = null ;
490+ let firstTargetUri = uri ;
491+
492+ if ( isExternalStorageUri ) {
493+ baseFolder = decodeURIComponent ( currentUri . split ( "%3A" ) [ 1 ] . split ( "/" ) [ 0 ] ) ;
513494 }
514- let tileType ;
515- if ( isFile && parts . length === 1 ) {
516- tileType = "file" ;
517- } else {
518- const urlParts = currentUri . split ( "/" ) ;
519- const pathParts = pathString . split ( "/" ) ;
520- const pathStartIndex = urlParts . findIndex (
521- ( part ) => part === pathParts [ 0 ] ,
495+ if ( parts [ 0 ] ) {
496+ firstTargetUri = getTargetUri ( uri , parts [ 0 ] , 0 ) ;
497+ }
498+
499+ for ( let i = 0 ; i < parts . length ; i ++ ) {
500+ const isLastElement = i === parts . length - 1 ;
501+ const name = parts [ i ] ;
502+ const targetUri = getTargetUri ( currentUri , name , i ) ;
503+ const expectedType = getExpectedType ( isLastElement ) ;
504+ const entry = await ensureEntry (
505+ currentUri ,
506+ targetUri ,
507+ name ,
508+ expectedType ,
522509 ) ;
523- if ( pathStartIndex !== - 1 ) {
524- const pathEndIndex = pathStartIndex + pathParts . length ;
525- urlParts . splice ( pathStartIndex + 1 , pathEndIndex - pathStartIndex - 1 ) ;
510+
511+ if ( entry . created && firstCreatedPath === null ) {
512+ firstCreatedPath = entry . url ;
513+ firstCreatedType = expectedType ;
526514 }
527- currentUri = urlParts . join ( "/" ) ;
528- tileType = "folder" ;
515+
516+ currentUri = entry . url ;
529517 }
530- return { uri : currentUri , type : tileType } ;
518+
519+ return {
520+ uri : firstCreatedPath || firstTargetUri ,
521+ type :
522+ firstCreatedType || ( isFile && parts . length === 1 ? "file" : "folder" ) ,
523+ } ;
531524 } ,
532525 formatDownloadCount ( downloadCount ) {
533526 const units = [ "" , "K" , "M" , "B" , "T" ] ;
0 commit comments