@@ -7,7 +7,9 @@ package integration
77import (
88 "errors"
99 "fmt"
10+ "io"
1011 "math/rand"
12+ "net/http"
1113 "net/url"
1214 "os"
1315 "path"
@@ -56,6 +58,63 @@ func doCreateRemoteAnnexRepository(t *testing.T, u *url.URL, ctx APITestContext,
5658 return nil
5759}
5860
61+ func TestGitAnnexMedia (t * testing.T ) {
62+ if ! setting .Annex .Enabled {
63+ t .Skip ("Skipping since annex support is disabled." )
64+ }
65+
66+ onGiteaRun (t , func (t * testing.T , u * url.URL ) {
67+ ctx := NewAPITestContext (t , "user2" , "annex-media-test" , auth_model .AccessTokenScopeWriteRepository )
68+
69+ // create a public repo
70+ require .NoError (t , doCreateRemoteAnnexRepository (t , u , ctx , false ))
71+
72+ // the filenames here correspond to specific cases defined in doInitAnnexRepository()
73+ t .Run ("AnnexSymlink" , func (t * testing.T ) {
74+ defer tests .PrintCurrentTest (t )()
75+ doAnnexMediaTest (t , ctx , "annexed.tiff" )
76+ })
77+ t .Run ("AnnexPointer" , func (t * testing.T ) {
78+ defer tests .PrintCurrentTest (t )()
79+ doAnnexMediaTest (t , ctx , "annexed.bin" )
80+ })
81+ })
82+ }
83+
84+ func doAnnexMediaTest (t * testing.T , ctx APITestContext , file string ) {
85+ // Make sure that downloading via /media on the website recognizes it should give the annexed content
86+
87+ // TODO:
88+ // - [ ] roll this into TestGitAnnexPermissions to ensure that permission enforcement works correctly even on /media?
89+
90+ session := loginUser (t , ctx .Username ) // logs in to the http:// site/API, storing a cookie;
91+ // this is a different auth method than the git+ssh:// or git+http:// protocols TestGitAnnexPermissions uses!
92+
93+ // compute server-side path of the annexed file
94+ remoteRepoPath := path .Join (setting .RepoRootPath , ctx .GitPath ())
95+ remoteObjectPath , err := contentLocation (remoteRepoPath , file )
96+ require .NoError (t , err )
97+
98+ // download annexed file
99+ localObjectPath := path .Join (t .TempDir (), file )
100+ fd , err := os .OpenFile (localObjectPath , os .O_CREATE | os .O_WRONLY , 0o777 )
101+ defer fd .Close ()
102+ require .NoError (t , err )
103+
104+ mediaLink := path .Join ("/" , ctx .Username , ctx .Reponame , "/media/branch/master" , file )
105+ req := NewRequest (t , "GET" , mediaLink )
106+ resp := session .MakeRequest (t , req , http .StatusOK )
107+
108+ _ , err = io .Copy (fd , resp .Body )
109+ require .NoError (t , err )
110+ fd .Close ()
111+
112+ // verify the download
113+ match , err := util .FileCmp (localObjectPath , remoteObjectPath , 0 )
114+ require .NoError (t , err )
115+ require .True (t , match , "Annexed files should be the same" )
116+ }
117+
59118/*
60119Test that permissions are enforced on git-annex-shell commands.
61120
@@ -763,16 +822,16 @@ func doAnnexInitTest(remoteRepoPath, repoPath string) (err error) {
763822 }
764823
765824 // - method 1: 'git annex whereis'.
766- // Demonstrates that git-annex understands the annexed file can be found in the remote annex.
767- annexWhereis , _ , err := git .NewCommandContextNoGlobals (git .DefaultContext , "annex" , "whereis" , "large .bin" ).RunStdString (& git.RunOpts {Dir : repoPath })
825+ // Demonstrates that git-annex understands annexed files can be found in the remote annex.
826+ annexWhereis , _ , err := git .NewCommandContextNoGlobals (git .DefaultContext , "annex" , "whereis" , "annexed .bin" ).RunStdString (& git.RunOpts {Dir : repoPath })
768827 if err != nil {
769- return fmt .Errorf ("Couldn't `git annex whereis large.bin `: %w" , err )
828+ return fmt .Errorf ("Couldn't `git annex whereis`: %w" , err )
770829 }
771830 // Note: this regex is unanchored because 'whereis' outputs multiple lines containing
772831 // headers and 1+ remotes and we just want to find one of them.
773832 match = regexp .MustCompile (regexp .QuoteMeta (remoteAnnexUUID ) + " -- .* \\ [origin\\ ]\n " ).MatchString (annexWhereis )
774833 if ! match {
775- return errors .New ("'git annex whereis' should report large.bin is known to be in [origin]" )
834+ return errors .New ("'git annex whereis' should report files are known to be in [origin]" )
776835 }
777836
778837 return nil
@@ -788,27 +847,56 @@ func doAnnexDownloadTest(remoteRepoPath, repoPath string) (err error) {
788847 return err
789848 }
790849
791- // verify the file was downloaded
792- localObjectPath , err := contentLocation (repoPath , "large.bin" )
793- if err != nil {
794- return err
850+ // verify the files downloaded
851+
852+ cmp := func (filename string ) error {
853+ localObjectPath , err := contentLocation (repoPath , filename )
854+ if err != nil {
855+ return err
856+ }
857+ // localObjectPath := path.Join(repoPath, filename) // or, just compare against the checked-out file
858+
859+ remoteObjectPath , err := contentLocation (remoteRepoPath , filename )
860+ if err != nil {
861+ return err
862+ }
863+
864+ match , err := util .FileCmp (localObjectPath , remoteObjectPath , 0 )
865+ if err != nil {
866+ return err
867+ }
868+ if ! match {
869+ return errors .New ("Annexed files should be the same" )
870+ }
871+
872+ return nil
795873 }
796- // localObjectPath := path.Join(repoPath, "large.bin") // or, just compare against the checked-out file
797874
798- remoteObjectPath , err := contentLocation (remoteRepoPath , "large.bin" )
875+ // this is the annex-symlink file
876+ stat , err := os .Lstat (path .Join (repoPath , "annexed.tiff" ))
799877 if err != nil {
878+ return fmt .Errorf ("Lstat: %w" , err )
879+ }
880+ if ! ((stat .Mode () & os .ModeSymlink ) != 0 ) {
881+ // this line is really just double-checking that the text fixture is set up correctly
882+ return errors .New ("*.tiff should be a symlink" )
883+ }
884+ if err = cmp ("annexed.tiff" ); err != nil {
800885 return err
801886 }
802887
803- match , err := util .FileCmp (localObjectPath , remoteObjectPath , 0 )
888+ // this is the annex-pointer file
889+ stat , err = os .Lstat (path .Join (repoPath , "annexed.bin" ))
804890 if err != nil {
805- return err
891+ return fmt . Errorf ( "Lstat: %w" , err )
806892 }
807- if ! match {
808- return errors .New ("Annexed files should be the same" )
893+ if ! ((stat .Mode () & os .ModeSymlink ) == 0 ) {
894+ // this line is really just double-checking that the text fixture is set up correctly
895+ return errors .New ("*.bin should not be a symlink" )
809896 }
897+ err = cmp ("annexed.bin" )
810898
811- return nil
899+ return err
812900}
813901
814902func doAnnexUploadTest (remoteRepoPath , repoPath string ) (err error ) {
@@ -953,16 +1041,36 @@ func doInitAnnexRepository(repoPath string) error {
9531041 return err
9541042 }
9551043
956- // add a file to the annex
957- err = generateRandomFile (1024 * 1024 / 4 , path .Join (repoPath , "large.bin" ))
1044+ // add files to the annex, stored via annex symlinks
1045+ // // a binary file
1046+ err = generateRandomFile (1024 * 1024 / 4 , path .Join (repoPath , "annexed.tiff" ))
1047+ if err != nil {
1048+ return err
1049+ }
1050+
1051+ err = git .NewCommandContextNoGlobals (git .DefaultContext , "annex" , "add" , "." ).Run (& git.RunOpts {Dir : repoPath })
1052+ if err != nil {
1053+ return err
1054+ }
1055+
1056+ // add files to the annex, stored via git-annex-smudge
1057+ // // a binary file
1058+ err = generateRandomFile (1024 * 1024 / 4 , path .Join (repoPath , "annexed.bin" ))
1059+ if err != nil {
1060+ return err
1061+ }
1062+
9581063 if err != nil {
9591064 return err
9601065 }
1066+
9611067 err = git .AddChanges (repoPath , false , "." )
9621068 if err != nil {
9631069 return err
9641070 }
965- err = git .CommitChanges (repoPath , git.CommitChangesOptions {Message : "Annex a file" })
1071+
1072+ // save everything
1073+ err = git .CommitChanges (repoPath , git.CommitChangesOptions {Message : "Annex files" })
9661074 if err != nil {
9671075 return err
9681076 }
0 commit comments