@@ -390,204 +390,6 @@ func (s *Server) doSnapshotJSON(ctx context.Context, method, workspaceID, path,
390390 }
391391 return nil
392392}
393- func createWIPBundle (ctx context.Context , workDir string , entryThreshold int64 ) (string , string , []snapshotSkippedEntry , error ) {
394- if ok , err := standaloneRepositoryPresent (workDir ); err != nil || ! ok {
395- if err != nil {
396- return "" , "" , nil , err
397- }
398- return "" , "" , nil , nil
399- }
400- if gitOperationInProgress (workDir ) {
401- return "" , "" , []snapshotSkippedEntry {{Path : workDir , Reason : "git operation in progress" }}, nil
402- }
403- base , err := runStandaloneGitCommand (ctx , workDir , nil , "rev-parse" , "HEAD" )
404- if err != nil {
405- return "" , "" , nil , fmt .Errorf ("resolve base commit: %w" , err )
406- }
407- status , err := runStandaloneGitCommand (ctx , workDir , nil , "status" , "--porcelain" )
408- if err != nil {
409- return base , "" , nil , fmt .Errorf ("git status: %w" , err )
410- }
411- if strings .TrimSpace (status ) == "" {
412- return base , "" , nil , nil
413- }
414-
415- indexFile , err := os .CreateTemp ("" , "sam-session-index-*" )
416- if err != nil {
417- return base , "" , nil , err
418- }
419- indexPath := indexFile .Name ()
420- _ = indexFile .Close ()
421- _ = os .Remove (indexPath )
422- defer os .Remove (indexPath )
423- gitEnv := []string {"GIT_INDEX_FILE=" + indexPath }
424- if _ , err := runStandaloneGitCommand (ctx , workDir , gitEnv , "read-tree" , "HEAD" ); err != nil {
425- return base , "" , nil , fmt .Errorf ("initialize snapshot index: %w" , err )
426- }
427- if _ , err := runStandaloneGitCommand (ctx , workDir , gitEnv , "add" , "-A" ); err != nil {
428- return base , "" , nil , fmt .Errorf ("stage snapshot index: %w" , err )
429- }
430- skipped := skipOversizedUntracked (workDir , entryThreshold )
431- for _ , entry := range skipped {
432- if entry .Path != "" {
433- _ , _ = runStandaloneGitCommand (ctx , workDir , gitEnv , "reset" , "--" , entry .Path )
434- }
435- }
436- tree , err := runStandaloneGitCommand (ctx , workDir , gitEnv , "write-tree" )
437- if err != nil {
438- return base , "" , skipped , fmt .Errorf ("write snapshot tree: %w" , err )
439- }
440- commitEnv := append (gitEnv , "GIT_AUTHOR_NAME=SAM Snapshot" , "GIT_AUTHOR_EMAIL=snapshot@localhost" , "GIT_COMMITTER_NAME=SAM Snapshot" , "GIT_COMMITTER_EMAIL=snapshot@localhost" )
441- commit , err := runStandaloneGitCommand (ctx , workDir , commitEnv , "commit-tree" , tree , "-p" , base , "-m" , "SAM session snapshot" )
442- if err != nil {
443- return base , "" , skipped , fmt .Errorf ("create snapshot commit: %w" , err )
444- }
445- bundle , err := os .CreateTemp ("" , "sam-session-wip-*.bundle" )
446- if err != nil {
447- return base , "" , skipped , err
448- }
449- bundlePath := bundle .Name ()
450- _ = bundle .Close ()
451- snapshotRef := "refs/sam/session-snapshot/" + strings .TrimSuffix (filepath .Base (bundlePath ), ".bundle" )
452- if _ , err := runStandaloneGitCommand (ctx , workDir , nil , "update-ref" , snapshotRef , commit ); err != nil {
453- _ = os .Remove (bundlePath )
454- return base , "" , skipped , fmt .Errorf ("create snapshot ref: %w" , err )
455- }
456- defer func () {
457- _ , _ = runStandaloneGitCommand (context .Background (), workDir , nil , "update-ref" , "-d" , snapshotRef )
458- }()
459- if _ , err := runStandaloneGitCommand (ctx , workDir , nil , "bundle" , "create" , bundlePath , snapshotRef ); err != nil {
460- _ = os .Remove (bundlePath )
461- return base , "" , skipped , fmt .Errorf ("create git bundle: %w" , err )
462- }
463- return base , bundlePath , skipped , nil
464- }
465- func gitOperationInProgress (workDir string ) bool {
466- gitDir := filepath .Join (workDir , ".git" )
467- for _ , marker := range []string {"MERGE_HEAD" , "CHERRY_PICK_HEAD" , "REVERT_HEAD" , "rebase-merge" , "rebase-apply" } {
468- if _ , err := os .Stat (filepath .Join (gitDir , marker )); err == nil {
469- return true
470- }
471- }
472- return false
473- }
474-
475- func skipOversizedUntracked (workDir string , threshold int64 ) []snapshotSkippedEntry {
476- var skipped []snapshotSkippedEntry
477- _ = filepath .WalkDir (workDir , func (path string , d os.DirEntry , err error ) error {
478- if err != nil || path == workDir {
479- return nil
480- }
481- if d .IsDir () && d .Name () == ".git" {
482- return filepath .SkipDir
483- }
484- if d .IsDir () {
485- return nil
486- }
487- info , statErr := d .Info ()
488- if statErr != nil || info .Size () <= threshold {
489- return nil
490- }
491- rel , _ := filepath .Rel (workDir , path )
492- if out , gitErr := runStandaloneGitCommand (context .Background (), workDir , nil , "check-ignore" , "-q" , rel ); gitErr == nil && strings .TrimSpace (out ) == "" {
493- return nil
494- }
495- skipped = append (skipped , snapshotSkippedEntry {Path : rel , Reason : "entry exceeds size threshold" , SizeBytes : info .Size ()})
496- return nil
497- })
498- return skipped
499- }
500-
501- func createHomeTar (homeDirFn func () (string , error ), entryThreshold , totalBudget int64 ) (string , []snapshotSkippedEntry , error ) {
502- home , err := homeDirFn ()
503- if err != nil {
504- return "" , nil , err
505- }
506- home = filepath .Clean (home )
507- out , err := os .CreateTemp ("" , "sam-session-home-*.tar" )
508- if err != nil {
509- return "" , nil , err
510- }
511- path := out .Name ()
512- tw := tar .NewWriter (out )
513- var written int64
514- var skipped []snapshotSkippedEntry
515- walkErr := filepath .WalkDir (home , func (path string , d os.DirEntry , err error ) error {
516- if err != nil || path == home {
517- return nil
518- }
519- rel , _ := filepath .Rel (home , path )
520- if shouldExcludeHomePath (rel ) {
521- if d .IsDir () {
522- return filepath .SkipDir
523- }
524- return nil
525- }
526- info , statErr := d .Info ()
527- if statErr != nil {
528- return nil
529- }
530- if info .Size () > entryThreshold {
531- skipped = append (skipped , snapshotSkippedEntry {Path : "~/" + rel , Reason : "entry exceeds size threshold" , SizeBytes : info .Size ()})
532- if d .IsDir () {
533- return filepath .SkipDir
534- }
535- return nil
536- }
537- if ! info .Mode ().IsRegular () && ! info .IsDir () {
538- skipped = append (skipped , snapshotSkippedEntry {Path : "~/" + rel , Reason : "unsupported home entry type" })
539- return nil
540- }
541- if ! info .IsDir () && written + info .Size () > totalBudget {
542- skipped = append (skipped , snapshotSkippedEntry {Path : "~/" + rel , Reason : "snapshot budget exhausted" , SizeBytes : info .Size ()})
543- return nil
544- }
545- header , headerErr := tar .FileInfoHeader (info , "" )
546- if headerErr != nil {
547- return nil
548- }
549- header .Name = rel
550- if err := tw .WriteHeader (header ); err != nil {
551- return err
552- }
553- if info .Mode ().IsRegular () {
554- f , openErr := os .Open (path )
555- if openErr != nil {
556- return nil
557- }
558- n , copyErr := io .Copy (tw , f )
559- _ = f .Close ()
560- written += n
561- if copyErr != nil {
562- return copyErr
563- }
564- }
565- return nil
566- })
567- closeErr := tw .Close ()
568- fileCloseErr := out .Close ()
569- if walkErr != nil || closeErr != nil || fileCloseErr != nil {
570- _ = os .Remove (path )
571- if walkErr != nil {
572- return "" , skipped , walkErr
573- }
574- if closeErr != nil {
575- return "" , skipped , closeErr
576- }
577- return "" , skipped , fileCloseErr
578- }
579- return path , skipped , nil
580- }
581-
582- func shouldExcludeHomePath (rel string ) bool {
583- first := strings .Split (filepath .ToSlash (rel ), "/" )[0 ]
584- switch first {
585- case ".cache" , ".npm" , ".cargo" , ".rustup" , ".local" , "node_modules" , ".docker" :
586- return true
587- default :
588- return false
589- }
590- }
591393
592394func (s * Server ) uploadSnapshotFile (ctx context.Context , uploadPath , filePath , token string , idleTimeout time.Duration ) (int64 , string , error ) {
593395 target := absoluteControlPlaneURL (s .config .ControlPlaneURL , uploadPath )
@@ -788,25 +590,3 @@ func choosePositiveDurationMs(value int64, fallback time.Duration) time.Duration
788590 }
789591 return fallback
790592}
791-
792- func rejectSymlinkPath (root , target string ) error {
793- rel , err := filepath .Rel (root , target )
794- if err != nil || rel == "." || rel == ".." || strings .HasPrefix (rel , ".." + string (filepath .Separator )) {
795- return fmt .Errorf ("snapshot target is outside home" )
796- }
797- current := root
798- for _ , part := range strings .Split (rel , string (filepath .Separator )) {
799- current = filepath .Join (current , part )
800- info , statErr := os .Lstat (current )
801- if os .IsNotExist (statErr ) {
802- continue
803- }
804- if statErr != nil {
805- return statErr
806- }
807- if info .Mode ()& os .ModeSymlink != 0 {
808- return fmt .Errorf ("snapshot target traverses symlink: %s" , rel )
809- }
810- }
811- return nil
812- }
0 commit comments