This repository has been archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1590 from OpenBazaar/listingmigration
Create migration029
- Loading branch information
Showing
2 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package migrations | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/OpenBazaar/openbazaar-go/ipfs" | ||
"github.com/ipfs/go-ipfs/core/mock" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
) | ||
|
||
// Migration029 will update the hashes of each listing in the listing index with | ||
// the newest hash format. | ||
type Migration029 struct{} | ||
|
||
type Migration029_Price struct { | ||
CurrencyCode string `json:"currencyCode"` | ||
Amount uint64 `json:"amount"` | ||
Modifier float32 `json:"modifier"` | ||
} | ||
type Migration029_Thumbnail struct { | ||
Tiny string `json:"tiny"` | ||
Small string `json:"small"` | ||
Medium string `json:"medium"` | ||
} | ||
|
||
type Migration029_ListingData struct { | ||
Hash string `json:"hash"` | ||
Slug string `json:"slug"` | ||
Title string `json:"title"` | ||
Categories []string `json:"categories"` | ||
NSFW bool `json:"nsfw"` | ||
ContractType string `json:"contractType"` | ||
Description string `json:"description"` | ||
Thumbnail Migration029_Thumbnail `json:"thumbnail"` | ||
Price Migration029_Price `json:"price"` | ||
ShipsTo []string `json:"shipsTo"` | ||
FreeShipping []string `json:"freeShipping"` | ||
Language string `json:"language"` | ||
AverageRating float32 `json:"averageRating"` | ||
RatingCount uint32 `json:"ratingCount"` | ||
ModeratorIDs []string `json:"moderators"` | ||
AcceptedCurrencies []string `json:"acceptedCurrencies"` | ||
CoinType string `json:"coinType"` | ||
} | ||
|
||
func (Migration029) Up(repoPath, databasePassword string, testnetEnabled bool) error { | ||
listingsFilePath := path.Join(repoPath, "root", "listings.json") | ||
|
||
// Non-vendors might not have an listing.json and we don't want to error here if that's the case | ||
indexExists := true | ||
if _, err := os.Stat(listingsFilePath); os.IsNotExist(err) { | ||
indexExists = false | ||
fmt.Println(listingsFilePath) | ||
} | ||
|
||
if indexExists { | ||
var listingIndex []Migration029_ListingData | ||
listingsJSON, err := ioutil.ReadFile(listingsFilePath) | ||
if err != nil { | ||
return err | ||
} | ||
if err = json.Unmarshal(listingsJSON, &listingIndex); err != nil { | ||
return err | ||
} | ||
n, err := coremock.NewMockNode() | ||
if err != nil { | ||
return err | ||
} | ||
for i, listing := range listingIndex { | ||
hash, err := ipfs.GetHashOfFile(n, path.Join(repoPath, "root", "listings", listing.Slug+".json")) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
listingIndex[i].Hash = hash | ||
} | ||
migratedJSON, err := json.MarshalIndent(&listingIndex, "", " ") | ||
if err != nil { | ||
return err | ||
} | ||
err = ioutil.WriteFile(listingsFilePath, migratedJSON, os.ModePerm) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return writeRepoVer(repoPath, 30) | ||
} | ||
|
||
func (Migration029) Down(repoPath, databasePassword string, testnetEnabled bool) error { | ||
// Down migration is a no-op (outside of updating the version) | ||
// We can't calculate the old style hash format anymore. | ||
return writeRepoVer(repoPath, 29) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package migrations_test | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/OpenBazaar/jsonpb" | ||
"github.com/OpenBazaar/openbazaar-go/pb" | ||
"github.com/OpenBazaar/openbazaar-go/repo/migrations" | ||
"github.com/OpenBazaar/openbazaar-go/schema" | ||
"github.com/OpenBazaar/openbazaar-go/test/factory" | ||
"io/ioutil" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestMigration029(t *testing.T) { | ||
var testRepo, err = schema.NewCustomSchemaManager(schema.SchemaContext{ | ||
DataPath: schema.GenerateTempPath(), | ||
TestModeEnabled: true, | ||
}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if err = testRepo.BuildSchemaDirectories(); err != nil { | ||
t.Fatal(err) | ||
} | ||
defer testRepo.DestroySchemaDirectories() | ||
|
||
var ( | ||
repoverPath = testRepo.DataPathJoin("repover") | ||
listingIndexPath = testRepo.DataPathJoin("root", "listings.json") | ||
testListingSlug = "Migration029_test_listing" | ||
testListingPath = testRepo.DataPathJoin("root", "listings", testListingSlug+".json") | ||
|
||
// This listing hash is generated using the default IPFS hashing algorithm as of v0.4.19 | ||
// If the default hashing algorithm changes at any point in the future you can expect this | ||
// test to fail and it will need to be updated to maintain the functionality of this migration. | ||
expectedListingHash = "QmfEr6qqLxRsjJhk1XPq2FBP6aiwG6w6Dwr1XepU1Rg1Wx" | ||
|
||
listing = factory.NewListing(testListingSlug) | ||
m = jsonpb.Marshaler{ | ||
Indent: " ", | ||
EmitDefaults: true, | ||
} | ||
) | ||
|
||
f, err := os.Create(testListingPath) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if err := m.Marshal(f, listing); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
index := []*migrations.Migration029_ListingData{extractListingData(listing)} | ||
indexJSON, err := json.MarshalIndent(&index, "", " ") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if err := ioutil.WriteFile(listingIndexPath, indexJSON, os.ModePerm); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
var migration migrations.Migration029 | ||
if err := migration.Up(testRepo.DataPath(), "", true); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
var listingIndex []migrations.Migration029_ListingData | ||
listingsJSON, err := ioutil.ReadFile(listingIndexPath) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if err = json.Unmarshal(listingsJSON, &listingIndex); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// See comment above on expectedListingHash | ||
if listingIndex[0].Hash != expectedListingHash { | ||
t.Errorf("Expected listing hash %s got %s", expectedListingHash, listingIndex[0].Hash) | ||
} | ||
|
||
assertCorrectRepoVer(t, repoverPath, "30") | ||
|
||
if err := migration.Down(testRepo.DataPath(), "", true); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
assertCorrectRepoVer(t, repoverPath, "29") | ||
} | ||
|
||
func extractListingData(listing *pb.Listing) *migrations.Migration029_ListingData { | ||
descriptionLength := len(listing.Item.Description) | ||
|
||
contains := func(s []string, e string) bool { | ||
for _, a := range s { | ||
if a == e { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
var shipsTo []string | ||
var freeShipping []string | ||
for _, shippingOption := range listing.ShippingOptions { | ||
for _, region := range shippingOption.Regions { | ||
if !contains(shipsTo, region.String()) { | ||
shipsTo = append(shipsTo, region.String()) | ||
} | ||
for _, service := range shippingOption.Services { | ||
if service.Price == 0 && !contains(freeShipping, region.String()) { | ||
freeShipping = append(freeShipping, region.String()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
ld := &migrations.Migration029_ListingData{ | ||
Hash: "aabbcc", | ||
Slug: listing.Slug, | ||
Title: listing.Item.Title, | ||
Categories: listing.Item.Categories, | ||
NSFW: listing.Item.Nsfw, | ||
CoinType: listing.Metadata.CoinType, | ||
ContractType: listing.Metadata.ContractType.String(), | ||
Description: listing.Item.Description[:descriptionLength], | ||
Thumbnail: migrations.Migration029_Thumbnail{listing.Item.Images[0].Tiny, listing.Item.Images[0].Small, listing.Item.Images[0].Medium}, | ||
Price: migrations.Migration029_Price{ | ||
CurrencyCode: listing.Metadata.PricingCurrency, | ||
Amount: listing.Item.Price, | ||
Modifier: listing.Metadata.PriceModifier, | ||
}, | ||
ShipsTo: shipsTo, | ||
FreeShipping: freeShipping, | ||
Language: listing.Metadata.Language, | ||
ModeratorIDs: listing.Moderators, | ||
AcceptedCurrencies: listing.Metadata.AcceptedCurrencies, | ||
} | ||
return ld | ||
} |