@@ -17,6 +17,7 @@ limitations under the License.
1717package cmd
1818
1919import (
20+ "errors"
2021 "fmt"
2122 "log"
2223 "os"
@@ -228,6 +229,8 @@ var suggestions = []prompt.Suggest{
228229 {Text : "cd" , Description : "change path" },
229230 {Text : "download" , Description : "download file from dfs to local machine" },
230231 {Text : "upload" , Description : "upload file from local machine to dfs" },
232+ {Text : "uploadDir" , Description : "upload a dir from local machine to dfs" },
233+ {Text : "downloadDir" , Description : "download dir from dfs to local machine" },
231234 {Text : "share" , Description : "share file with another user" },
232235 {Text : "receive" , Description : "receive a shared file" },
233236 {Text : "exit" , Description : "exit dfs-prompt" },
@@ -297,7 +300,6 @@ func executor(in string) {
297300 mnemonic = strings .TrimPrefix (mnemonic , " " )
298301 }
299302 userNew (userName , mnemonic )
300- currentUser = userName
301303 currentPod = ""
302304 currentDirectory = ""
303305 currentPrompt = getCurrentPrompt ()
@@ -750,7 +752,10 @@ func executor(in string) {
750752 if ! isPodOpened () {
751753 return
752754 }
753- listFileAndDirectories (currentPod , currentDirectory )
755+ _ , err = listFileAndDirectories (currentPod , currentDirectory )
756+ if err != nil {
757+ fmt .Println ("ls failed: " , err )
758+ }
754759 currentPrompt = getCurrentPrompt ()
755760 case "mkdir" :
756761 if ! isPodOpened () {
@@ -797,6 +802,81 @@ func executor(in string) {
797802 }
798803 rmDir (currentPod , dirToRm )
799804 currentPrompt = getCurrentPrompt ()
805+ case "uploadDir" :
806+ if ! isPodOpened () {
807+ return
808+ }
809+ if len (blocks ) < 4 {
810+ fmt .Println ("invalid command. Missing one or more arguments" )
811+ return
812+ }
813+ dirName := blocks [1 ]
814+ podDir := blocks [2 ]
815+ if podDir == "." {
816+ podDir = currentDirectory
817+ }
818+ blockSize := blocks [3 ]
819+ compression := ""
820+ if len (blocks ) >= 5 {
821+ compression = blocks [4 ]
822+ if compression != "snappy" && compression != "gzip" {
823+ fmt .Println ("invalid value for \" compression\" , should either be \" snappy\" or \" gzip\" " )
824+ return
825+ }
826+ }
827+ toUpload , err := findFilesToUpload (dirName )
828+ if err != nil {
829+ fmt .Println ("Failed to list files to upload at: " , dirName , err )
830+ return
831+ }
832+ for _ , item := range toUpload .filesToUpload {
833+ if toUpload .rootDirectory != item {
834+ itemStats , err := os .Stat (item )
835+ if err != nil {
836+ fmt .Println ("Failed to read stats for: " , item , err )
837+ continue
838+ }
839+ fmt .Println ("Handling item: " , removeParentDirectory (toUpload .rootDirectory , item ))
840+ if itemStats .IsDir () {
841+ dirToMk := filepath .ToSlash (filepath .Join (podDir , removeParentDirectory (toUpload .rootDirectory , item )))
842+ mkdir (currentPod , dirToMk )
843+ } else {
844+ filePath := removeParentDirectory (toUpload .rootDirectory , item )
845+ uploadFile (filepath .Base (filePath ), currentPod , item , filepath .ToSlash (filepath .Join (podDir , filepath .Dir (filePath ))), blockSize , compression )
846+ }
847+ }
848+ }
849+ currentPrompt = getCurrentPrompt ()
850+ case "downloadDir" :
851+ if ! isPodOpened () {
852+ return
853+ }
854+ if len (blocks ) < 3 {
855+ fmt .Println ("invalid command. Missing one or more arguments" )
856+ return
857+ }
858+ localDir := blocks [1 ]
859+ dirStat , err := os .Stat (localDir )
860+ if err != nil {
861+ fmt .Println ("local path is not a present: " , err )
862+ return
863+ }
864+
865+ if ! dirStat .IsDir () {
866+ fmt .Println ("local path is not a directory" )
867+ return
868+ }
869+
870+ podPath := blocks [2 ]
871+ if ! strings .HasPrefix (podPath , utils .PathSeparator ) {
872+ if currentDirectory == utils .PathSeparator {
873+ podPath = currentDirectory + podPath
874+ } else {
875+ podPath = currentDirectory + utils .PathSeparator + podPath
876+ }
877+ }
878+ downloadDir (currentPod , localDir , podPath )
879+ currentPrompt = getCurrentPrompt ()
800880 case "upload" :
801881 if ! isPodOpened () {
802882 return
@@ -988,6 +1068,8 @@ func help() {
9881068 fmt .Println (" - ls " )
9891069 fmt .Println (" - download <destination dir in local fs> <relative path of source file in pod>" )
9901070 fmt .Println (" - upload <source file in local fs> <destination directory in pod> <block size (ex: 1Mb, 64Mb)>, <compression (snappy/gzip)>" )
1071+ fmt .Println (" - uploadDir <source location in local fs> <destination directory in pod> <block size (ex: 1Mb, 64Mb)>, <compression (snappy/gzip)>" )
1072+ fmt .Println (" - downloadDir <destination location in local fs> <source directory in pod>" )
9911073 fmt .Println (" - share <file name> - shares a file with another user" )
9921074 fmt .Println (" - receive <sharing reference> <pod dir> - receives a file from another user" )
9931075 fmt .Println (" - receiveinfo <sharing reference> - shows the received file info before accepting the receive" )
@@ -1050,3 +1132,77 @@ func getPassword() (password string) {
10501132 password = strings .TrimSpace (passwd )
10511133 return password
10521134}
1135+
1136+ type files struct {
1137+ filesToUpload []string
1138+ rootDirectory string
1139+ }
1140+
1141+ func findFilesToUpload (searchPath string ) (* files , error ) {
1142+ searchResults := []string {}
1143+ rawSearchResults , err := filepath .Glob (searchPath )
1144+ if err != nil {
1145+ return nil , err
1146+ }
1147+
1148+ for _ , searchResult := range rawSearchResults {
1149+ searchResults = append (searchResults , searchResult )
1150+ fileStats , err := os .Stat (searchResult )
1151+ if err != nil {
1152+ return nil , err
1153+ }
1154+
1155+ if fileStats .IsDir () {
1156+ toUpload , err := findFilesToUpload (filepath .Join (searchResult , "*" ))
1157+ if err == nil {
1158+ searchResults = append (searchResults , toUpload .filesToUpload ... )
1159+ }
1160+ }
1161+ }
1162+
1163+ if len (searchResults ) == 1 && searchPath == searchResults [0 ] {
1164+ return & files {
1165+ filesToUpload : searchResults ,
1166+ rootDirectory : filepath .Dir (searchResults [0 ]),
1167+ }, nil
1168+ }
1169+
1170+ return & files {
1171+ filesToUpload : searchResults ,
1172+ rootDirectory : searchPath ,
1173+ }, nil
1174+ }
1175+
1176+ func removeParentDirectory (parentPath , childPath string ) string {
1177+ relativePath , err := filepath .Rel (parentPath , childPath )
1178+ if err != nil {
1179+ panic (err )
1180+ }
1181+ if relativePath == "" {
1182+ return "/"
1183+ }
1184+ if strings .HasPrefix (relativePath , ".." ) {
1185+ return ""
1186+ }
1187+ return "/" + relativePath
1188+ }
1189+
1190+ func downloadDir (currentPod , localDir , podPath string ) {
1191+ stat , err := listFileAndDirectories (currentPod , podPath )
1192+ if err != nil {
1193+ fmt .Println ("failed to get contents of dir: " , podPath , err )
1194+ return
1195+ }
1196+ for _ , dir := range stat .Directories {
1197+ err := os .Mkdir (filepath .Join (localDir , dir .Name ), os .FileMode (dir .Mode ))
1198+ if err != nil && ! errors .Is (err , os .ErrExist ) {
1199+ fmt .Println ("failed to create local dir: " , filepath .Join (localDir , dir .Name ), err )
1200+ continue
1201+ }
1202+ downloadDir (currentPod , filepath .Join (localDir , dir .Name ), filepath .ToSlash (filepath .Join (podPath , dir .Name )))
1203+ }
1204+ for _ , file := range stat .Files {
1205+ loalFile := filepath .Join (localDir , file .Name )
1206+ downloadFile (currentPod , loalFile , filepath .ToSlash (filepath .Join (podPath , file .Name )))
1207+ }
1208+ }
0 commit comments