diff --git a/examples/upload_download/main.go b/examples/upload_download/main.go new file mode 100644 index 000000000..500def9c9 --- /dev/null +++ b/examples/upload_download/main.go @@ -0,0 +1,38 @@ +// Command repository_api demonstrates the use of Kopia's Repository API. +package main + +import ( + "context" + "log" + "os" + + "github.com/kopia/repo" +) + +func main() { + ctx := context.Background() + + if err := setupRepositoryAndConnect(ctx, masterPassword); err != nil { + log.Printf("unable to set up repository: %v", err) + os.Exit(1) + } + + r, err := repo.Open(ctx, configFile, masterPassword, nil) + if err != nil { + log.Printf("unable to open repository: %v", err) + os.Exit(1) + } + defer r.Close(ctx) //nolint:errcheck + + uploadAndDownloadObjects(ctx, r) + + // Now list blocks found in the repository. + blks, err := r.Blocks.ListBlocks("") + if err != nil { + log.Printf("err: %v", err) + } + + for _, b := range blks { + log.Printf("found block %v", b) + } +} diff --git a/examples/upload_download/setup_repository.go b/examples/upload_download/setup_repository.go new file mode 100644 index 000000000..4bd928de1 --- /dev/null +++ b/examples/upload_download/setup_repository.go @@ -0,0 +1,54 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/kopia/repo" + "github.com/kopia/repo/block" + "github.com/kopia/repo/storage/filesystem" + "github.com/kopia/repo/storage/logging" +) + +const ( + masterPassword = "my-password$!@#!@" + storageDir = "/tmp/kopia-example/storage" + configFile = "/tmp/kopia-example/config" + cacheDirectory = "/tmp/kopia-example/cache" +) + +func setupRepositoryAndConnect(ctx context.Context, password string) error { + if err := os.MkdirAll(storageDir, 0700); err != nil { + return fmt.Errorf("unable to create directory: %v", err) + } + st, err := filesystem.New(ctx, &filesystem.Options{ + Path: storageDir, + }) + if err != nil { + return fmt.Errorf("unable to connect to storage: %v", err) + } + + // set up logging so we can see what's going on + st = logging.NewWrapper(st) + + // see if we already have the config file, if not connect. + if _, err := os.Stat(configFile); os.IsNotExist(err) { + // initialize repository + if err := repo.Initialize(ctx, st, &repo.NewRepositoryOptions{}, password); err != nil { + return fmt.Errorf("unable to initialize repository: %v", err) + } + + // now establish connection to repository and create configuration file. + if err := repo.Connect(ctx, configFile, st, password, repo.ConnectOptions{ + CachingOptions: block.CachingOptions{ + CacheDirectory: cacheDirectory, + MaxCacheSizeBytes: 100000000, + }, + }); err != nil { + return fmt.Errorf("unable to connect to repository: %v", err) + } + } + + return nil +} diff --git a/examples/upload_download/upload_download_objects.go b/examples/upload_download/upload_download_objects.go new file mode 100644 index 000000000..53e37cd7e --- /dev/null +++ b/examples/upload_download/upload_download_objects.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "crypto/rand" + "io/ioutil" + "log" + "os" + + "github.com/kopia/repo" + "github.com/kopia/repo/object" +) + +func uploadRandomObject(ctx context.Context, r *repo.Repository, length int) (object.ID, error) { + w := r.Objects.NewWriter(ctx, object.WriterOptions{}) + defer w.Close() //nolint:errcheck + + buf := make([]byte, 256*1024) + for length > 0 { + todo := length + if todo > len(buf) { + todo = len(buf) + } + rand.Read(buf[0:todo]) //nolint:errcheck + if _, err := w.Write(buf[0:todo]); err != nil { + return "", err + } + length -= todo + } + return w.Result() +} + +func downloadObject(ctx context.Context, r *repo.Repository, oid object.ID) ([]byte, error) { + rd, err := r.Objects.Open(ctx, oid) + if err != nil { + return nil, err + } + defer rd.Close() //nolint:errcheck + + return ioutil.ReadAll(rd) +} + +func uploadAndDownloadObjects(ctx context.Context, r *repo.Repository) { + var oids []object.ID + + for size := 100; size < 100000000; size *= 2 { + log.Printf("uploading file with %v bytes", size) + oid, err := uploadRandomObject(ctx, r, size) + if err != nil { + log.Printf("unable to upload: %v", err) + os.Exit(1) + } + log.Printf("uploaded %v bytes as %v", size, oid) + oids = append(oids, oid) + } + + for _, oid := range oids { + log.Printf("downloading %q", oid) + b, err := downloadObject(ctx, r, oid) + if err != nil { + log.Printf("unable to read object: %v", err) + } + log.Printf("downloaded %v", len(b)) + } +}