@@ -725,6 +725,157 @@ func UploadFilePost(ctx *context.Context) {
725725 }
726726}
727727
728+ // UploadFilePostJson JSON response for uploading file
729+ func UploadFilePostJson (ctx * context.Context ) {
730+ // `renderCommitRights` is a poorly named; it's not responsible directly for rendering anything,
731+ // it returns a boolean
732+ form := web .GetForm (ctx ).(* forms.UploadRepoFileForm )
733+ canCommit := renderCommitRights (ctx )
734+ oldBranchName := ctx .Repo .BranchName
735+ branchName := oldBranchName
736+
737+ if form .CommitChoice == frmCommitChoiceNewBranch {
738+ branchName = form .NewBranchName
739+ }
740+
741+ form .TreePath = cleanUploadFileName (form .TreePath )
742+
743+ treeNames , _ := getParentTreeFields (form .TreePath )
744+ if len (treeNames ) == 0 {
745+ // We must at least have one element for user to input.
746+ treeNames = []string {"" }
747+ }
748+ response := make (map [string ]string )
749+
750+ if ctx .HasError () {
751+ response ["message" ] = "Failed to commit the files"
752+ ctx .JSON (http .StatusUnprocessableEntity , response )
753+ log .Error ("failed to commit files" )
754+ return
755+ }
756+
757+ if oldBranchName != branchName {
758+ if _ , err := ctx .Repo .GitRepo .GetBranch (ctx .Repo .BranchName ); err == nil {
759+ response ["message" ] = "Branch already exists"
760+ ctx .JSON (http .StatusConflict , response )
761+ return
762+ }
763+ } else if ! canCommit {
764+ response ["message" ] = "Can't commit to protected branch"
765+ ctx .JSON (http .StatusUnauthorized , response )
766+ return
767+ }
768+
769+ var newTreePath string
770+ for _ , part := range treeNames {
771+ newTreePath = path .Join (newTreePath , part )
772+ entry , err := ctx .Repo .Commit .GetTreeEntryByPath (newTreePath )
773+ if err != nil {
774+ if git .IsErrNotExist (err ) {
775+ // Means there is no item with that name, so we're good
776+ break
777+ }
778+ response ["message" ] = "Something went wrong!"
779+ ctx .JSON (http .StatusInternalServerError , response )
780+ return
781+ }
782+
783+ // User can only upload files to a directory.
784+ if ! entry .IsDir () {
785+ ctx .Data ["Err_TreePath" ] = true
786+ ctx .RenderWithErr (ctx .Tr ("repo.editor.directory_is_a_file" , part ), tplUploadFile , & form )
787+ response ["message" ] = "A file with the same name of the new directory already exists."
788+ ctx .JSON (http .StatusConflict , response )
789+ return
790+ }
791+ }
792+
793+ message := strings .TrimSpace (form .CommitSummary )
794+ if len (message ) == 0 {
795+ message = ctx .Tr ("repo.editor.upload_files_to_dir" , form .TreePath )
796+ }
797+
798+ form .CommitMessage = strings .TrimSpace (form .CommitMessage )
799+ if len (form .CommitMessage ) > 0 {
800+ message += "\n \n " + form .CommitMessage
801+ }
802+
803+ if err := files_service .UploadRepoFiles (ctx , ctx .Repo .Repository , ctx .Doer , & files_service.UploadRepoFileOptions {
804+ LastCommitID : ctx .Repo .CommitID ,
805+ OldBranch : oldBranchName ,
806+ NewBranch : branchName ,
807+ TreePath : form .TreePath ,
808+ Message : message ,
809+ Files : form .Files ,
810+ }); err != nil {
811+ if models .IsErrLFSFileLocked (err ) {
812+ response ["message" ] = ctx .Tr ("repo.editor.upload_file_is_locked" )
813+ ctx .JSON (http .StatusUnauthorized , response )
814+ } else if models .IsErrFilenameInvalid (err ) {
815+ response ["message" ] = ctx .Tr ("repo.editor.filename_is_invalid" )
816+ ctx .JSON (http .StatusUnprocessableEntity , response )
817+ } else if models .IsErrFilePathInvalid (err ) {
818+ fileErr := err .(models.ErrFilePathInvalid )
819+ switch fileErr .Type {
820+ case git .EntryModeSymlink :
821+ response ["message" ] = ctx .Tr ("repo.editor.file_is_a_symlink" , fileErr .Path )
822+ ctx .JSON (http .StatusConflict , response )
823+ case git .EntryModeTree :
824+ response ["message" ] = ctx .Tr ("repo.editor.filename_is_a_directory" , fileErr .Path )
825+ ctx .JSON (http .StatusConflict , response )
826+ case git .EntryModeBlob :
827+ response ["message" ] = ctx .Tr ("repo.editor.directory_is_a_file" , fileErr .Path )
828+ ctx .JSON (http .StatusConflict , response )
829+ default :
830+ response ["message" ] = "Something went wrong"
831+ ctx .JSON (http .StatusInternalServerError , response )
832+ }
833+ } else if models .IsErrRepoFileAlreadyExists (err ) {
834+ response ["message" ] = ctx .Tr ("repo.editor.file_already_exists" , form .TreePath )
835+ ctx .JSON (http .StatusConflict , response )
836+ } else if git .IsErrBranchNotExist (err ) {
837+ branchErr := err .(git.ErrBranchNotExist )
838+ response ["message" ] = ctx .Tr ("repo.editor.branch_does_not_exist" , branchErr .Name )
839+ ctx .JSON (http .StatusNotFound , response )
840+ } else if models .IsErrBranchAlreadyExists (err ) {
841+ // For when a user specifies a new branch that already exists
842+ branchErr := err .(models.ErrBranchAlreadyExists )
843+ response ["message" ] = ctx .Tr ("repo.editor.branch_already_exists" , branchErr .BranchName )
844+ ctx .JSON (http .StatusConflict , response )
845+ } else if git .IsErrPushOutOfDate (err ) {
846+ response ["message" ] = ctx .Tr (
847+ "repo.editor.file_changed_while_editing" ,
848+ ctx .Repo .RepoLink + "/compare/" + ctx .Repo .CommitID + "..." + form .NewBranchName ,
849+ )
850+ ctx .JSON (http .StatusConflict , response )
851+ } else if git .IsErrPushRejected (err ) {
852+ errPushRej := err .(* git.ErrPushRejected )
853+ if len (errPushRej .Message ) == 0 {
854+ response ["message" ] = ctx .Tr ("repo.editor.push_rejected_no_message" )
855+ ctx .JSON (http .StatusConflict , response )
856+ } else {
857+ response ["response" ] = ctx .Tr ("repo.editor.push_rejected" , utils .SanitizeFlashErrorString (errPushRej .Message ))
858+ ctx .JSON (http .StatusConflict , response )
859+ }
860+ } else {
861+ // os.ErrNotExist - upload file missing in the intervening time?!
862+ log .Error (
863+ "Error during upload to repo: %-v to filepath: %s on %s from %s: %v" ,
864+ ctx .Repo .Repository ,
865+ form .TreePath ,
866+ oldBranchName ,
867+ form .NewBranchName ,
868+ err ,
869+ )
870+ response ["message" ] = ctx .Tr ("repo.editor.unable_to_upload_files" , form .TreePath , err )
871+ ctx .JSON (http .StatusInternalServerError , response )
872+ }
873+ return
874+ }
875+ response ["message" ] = "Committed files successfully."
876+ ctx .JSON (http .StatusCreated , response )
877+ }
878+
728879func cleanUploadFileName (name string ) string {
729880 // Rebase the filename
730881 name = strings .Trim (path .Clean ("/" + name ), "/" )
0 commit comments