github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/kbfstool/md_force_qr.go (about) 1 package main 2 3 import ( 4 "errors" 5 "flag" 6 "fmt" 7 8 "github.com/keybase/client/go/kbfs/kbfsmd" 9 "github.com/keybase/client/go/kbfs/libkbfs" 10 "github.com/keybase/client/go/protocol/keybase1" 11 "golang.org/x/net/context" 12 ) 13 14 func mdForceQROne( 15 ctx context.Context, config libkbfs.Config, 16 replacements replacementMap, input string, dryRun bool) error { 17 tlfStr, branchStr, startStr, stopStr, err := mdSplitInput(input) 18 if err != nil { 19 return err 20 } 21 22 _, branchID, start, stop, err := 23 mdParseInput(ctx, config, tlfStr, branchStr, startStr, stopStr) 24 if err != nil { 25 return err 26 } 27 28 if branchID != kbfsmd.NullBranchID { 29 return errors.New("force-qr doesn't support branch IDs") 30 } 31 if start != stop { 32 return errors.New("force-qr doesn't support revision ranges") 33 } 34 35 // Get the latest head, and add a QR record up to that point. 36 irmd, err := mdGetMergedHeadForWriter(ctx, config, tlfStr) 37 if err != nil { 38 return err 39 } 40 41 rmdNext, err := irmd.MakeSuccessor(ctx, config.MetadataVersion(), 42 config.Codec(), config.KeyManager(), 43 config.KBPKI(), config.KBPKI(), config, irmd.MdID(), true) 44 if err != nil { 45 return err 46 } 47 48 // Pretend like we've done quota reclamation up through the 49 // specified revision. 50 gco := &libkbfs.GCOp{ 51 LatestRev: start, 52 } 53 rmdNext.AddOp(gco) 54 rmdNext.SetLastGCRevision(start) 55 56 fmt.Printf( 57 "Will put a forced QR op up to revision %d:\n", start) 58 err = mdDumpReadOnlyRMD(ctx, config, "md forceQR", replacements, rmdNext.ReadOnly()) 59 if err != nil { 60 return err 61 } 62 63 if dryRun { 64 fmt.Print("Dry-run set; not doing anything\n") 65 return nil 66 } 67 68 fmt.Printf("Putting revision %d...\n", rmdNext.Revision()) 69 70 session, err := config.KBPKI().GetCurrentSession(ctx) 71 if err != nil { 72 return err 73 } 74 75 newIrmd, err := config.MDOps().Put( 76 ctx, rmdNext, session.VerifyingKey, nil, keybase1.MDPriorityNormal, nil) 77 if err != nil { 78 return err 79 } 80 81 fmt.Printf("New MD has revision %v\n", newIrmd.Revision()) 82 83 return nil 84 } 85 86 const mdForceQRUsageStr = `Usage: 87 kbfstool md forceQR /keybase/[public|private]/user1,assertion2 88 89 ` 90 91 func mdForceQR(ctx context.Context, config libkbfs.Config, 92 args []string) (exitStatus int) { 93 flags := flag.NewFlagSet("kbfs md forceQR", flag.ContinueOnError) 94 dryRun := flags.Bool("d", false, "Dry run: don't actually do anything.") 95 err := flags.Parse(args) 96 if err != nil { 97 printError("md forceQR", err) 98 return 1 99 } 100 101 inputs := flags.Args() 102 if len(inputs) != 1 { 103 fmt.Print(mdForceQRUsageStr) 104 return 1 105 } 106 107 replacements := make(replacementMap) 108 109 err = mdForceQROne(ctx, config, replacements, inputs[0], *dryRun) 110 if err != nil { 111 printError("md forceQR", err) 112 return 1 113 } 114 115 fmt.Print("\n") 116 117 return 0 118 }