Skip to content

Commit

Permalink
mod updates
Browse files Browse the repository at this point in the history
  • Loading branch information
BuckarooBanzay committed Sep 14, 2023
1 parent f479852 commit fc799c8
Show file tree
Hide file tree
Showing 17 changed files with 173 additions and 108 deletions.
14 changes: 14 additions & 0 deletions api/cdb/cached_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type CachedCDBClient struct {
search_cache *cache.Cache[string, []*Package]
dependency_cache *cache.Cache[string, PackageDependency]
detail_cache *cache.Cache[string, *PackageDetails]
updates PackageUpdates
updates_time time.Time
}

func NewCachedClient(client *CDBClient, ttl time.Duration) *CachedCDBClient {
Expand Down Expand Up @@ -69,3 +71,15 @@ func (c *CachedCDBClient) GetDetails(author, name string) (*PackageDetails, erro
}
return res, nil
}

func (c *CachedCDBClient) GetUpdates() (PackageUpdates, error) {
last_update := time.Since(c.updates_time)
if last_update > c.ttl || c.updates == nil {
var err error
c.updates, err = c.client.GetUpdates()
if err != nil {
return nil, err
}
}
return c.updates, nil
}
6 changes: 6 additions & 0 deletions api/cdb/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ func (c *CDBClient) GetRelease(author, name string, id int) (*PackageRelease, er
return pr, err
}

func (c *CDBClient) GetUpdates() (PackageUpdates, error) {
pu := PackageUpdates{}
err := c.get("api/updates", &pu, nil)
return pu, err
}

func (c *CDBClient) GetScreenshots(author, name string) ([]*PackageScreenshot, error) {
ps := []*PackageScreenshot{}
err := c.get(fmt.Sprintf("api/packages/%s/%s/screenshots", author, name), &ps, nil)
Expand Down
2 changes: 2 additions & 0 deletions api/cdb/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ type DependencyInfo struct {

type PackageDependency map[string][]*DependencyInfo

type PackageUpdates map[string]int

type MinetestVersion struct {
IsDev bool `json:"is_dev"`
Name string `json:"name"`
Expand Down
1 change: 1 addition & 0 deletions db/migrations/08_mod_latest_version.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table mod add column latest_version varchar(64) not null default '';
5 changes: 0 additions & 5 deletions modmanager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ func (m *ModManager) Create(mod *types.Mod) error {
return handler.Create(m.handlercontext, mod)
}

func (m *ModManager) Status(mod *types.Mod) (*ModStatus, error) {
handler := m.handlers[mod.SourceType]
return handler.Status(m.handlercontext, mod)
}

func (m *ModManager) Update(mod *types.Mod, version string) error {
handler := m.handlers[mod.SourceType]
return handler.Update(m.handlercontext, mod, version)
Expand Down
13 changes: 7 additions & 6 deletions modmanager/manager_cdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestLatestCDBRelease(t *testing.T) {
Name: "blockexchange",
ModType: types.ModTypeMod,
SourceType: types.SourceTypeCDB,
Author: "buckaroobanzay",
Author: "BuckarooBanzay",
}
assert.NoError(t, mm.Create(mod))
assert.True(t, mod.Version != "")
Expand All @@ -27,13 +27,14 @@ func TestLatestCDBRelease(t *testing.T) {
assert.NotNil(t, mods)
assert.Equal(t, 1, len(mods))

status, err := mm.Status(mod)
err = mm.CheckUpdates()
assert.NoError(t, err)
assert.NotNil(t, status)
assert.Equal(t, mod.Version, status.CurrentVersion)
assert.Equal(t, mod.Version, status.LatestVersion)

err = mm.Update(mod, mod.Version)
mod, err = app.Repos.ModRepo.GetByID(mod.ID)
assert.NoError(t, err)
assert.Equal(t, mod.Version, mod.LatestVersion)

err = mm.Update(mod, mod.LatestVersion)
assert.NoError(t, err)

err = mm.Remove(mod)
Expand Down
17 changes: 6 additions & 11 deletions modmanager/manager_git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,15 @@ func TestCheckoutHash(t *testing.T) {
assert.Equal(t, 1, len(mods))

// check remote status
status, err := mm.Status(mod)
err = mm.CheckUpdates()
assert.NoError(t, err)
assert.NotNil(t, status)
assert.Equal(t, "fe34e3f3cd3e066ba0be76f9df46c11e66411496", status.CurrentVersion)
assert.True(t, status.LatestVersion != "")
assert.True(t, status.LatestVersion != status.CurrentVersion)

// update
assert.NoError(t, mm.Update(mod, status.LatestVersion))
status2, err := mm.Status(mod)
mod, err = app.Repos.ModRepo.GetByID(mod.ID)
assert.NoError(t, err)
assert.NotNil(t, status2)
assert.Equal(t, status.LatestVersion, status2.CurrentVersion)
assert.Equal(t, status.LatestVersion, status2.LatestVersion)
assert.NotEqual(t, "fe34e3f3cd3e066ba0be76f9df46c11e66411496", mod.LatestVersion)

// update
assert.NoError(t, mm.Update(mod, mod.LatestVersion))

// remove
assert.NoError(t, mm.Remove(mod))
Expand Down
32 changes: 17 additions & 15 deletions modmanager/source_cdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import (
"path"
"strconv"
"strings"
"time"
)

var cli = cdb.New()
var cached_cli = cdb.NewCachedClient(cli, time.Hour)

type ContentDBModHandler struct{}

Expand Down Expand Up @@ -69,7 +71,6 @@ func (h *ContentDBModHandler) installMod(ctx *HandlerContext, mod *types.Mod, re
default:
return fmt.Errorf("mod type not supported: %s", mod.ModType)
}
fmt.Printf("Fullpath: '%s' entry: '%s'\n", fullpath, f.Name)

// create basedir if it does not exist
basedir := path.Dir(fullpath)
Expand Down Expand Up @@ -150,20 +151,6 @@ func (h *ContentDBModHandler) Create(ctx *HandlerContext, mod *types.Mod) error
return ctx.Repo.Create(mod)
}

func (h *ContentDBModHandler) Status(ctx *HandlerContext, mod *types.Mod) (*ModStatus, error) {
release, err := h.getLatestRelease(ctx, mod)
if err != nil {
return nil, fmt.Errorf("could not fetch latest release: %v", err)
}

s := &ModStatus{
CurrentVersion: mod.Version,
LatestVersion: fmt.Sprintf("%d", release.ID),
}

return s, nil
}

func (h *ContentDBModHandler) Update(ctx *HandlerContext, mod *types.Mod, version string) error {

release_id, err := strconv.Atoi(version)
Expand Down Expand Up @@ -196,3 +183,18 @@ func (h *ContentDBModHandler) Remove(ctx *HandlerContext, mod *types.Mod) error

return ctx.Repo.Delete(mod.ID)
}

func (h *ContentDBModHandler) CheckUpdate(ctx *HandlerContext, mod *types.Mod) (bool, error) {
updates, err := cached_cli.GetUpdates()
if err != nil {
return false, fmt.Errorf("could not get updates: %v", err)
}

v := updates[fmt.Sprintf("%s/%s", mod.Author, mod.Name)]
if v > 0 {
mod.LatestVersion = fmt.Sprintf("%d", v)
return true, nil
}

return false, nil
}
62 changes: 27 additions & 35 deletions modmanager/source_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,40 +70,6 @@ func (h *GitModHandler) Create(ctx *HandlerContext, mod *types.Mod) error {
return ctx.Repo.Create(mod)
}

func (h *GitModHandler) Status(ctx *HandlerContext, mod *types.Mod) (*ModStatus, error) {
status := &ModStatus{}

dir := getDir(ctx.WorldDir, mod)

r, err := git.PlainOpen(dir)
if err != nil {
return status, err
}

heah, err := r.Head()
if err != nil {
return status, err
}
status.CurrentVersion = heah.Hash().String()

rem := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
Name: "origin",
URLs: []string{mod.URL},
})

refs, err := rem.List(&git.ListOptions{})
if err != nil {
return status, err
}
for _, ref := range refs {
if ref.Name() == plumbing.ReferenceName(mod.Branch) {
status.LatestVersion = ref.Hash().String()
}
}

return status, nil
}

func (h *GitModHandler) Update(ctx *HandlerContext, mod *types.Mod, version string) error {
dir := getDir(ctx.WorldDir, mod)

Expand All @@ -122,9 +88,16 @@ func (h *GitModHandler) Update(ctx *HandlerContext, mod *types.Mod, version stri
return err
}

return w.Checkout(&git.CheckoutOptions{
err = w.Checkout(&git.CheckoutOptions{
Hash: plumbing.NewHash(version),
})
if err != nil {
return err
}

mod.Version = version
return ctx.Repo.Update(mod)

}

func (h *GitModHandler) Remove(ctx *HandlerContext, mod *types.Mod) error {
Expand All @@ -137,3 +110,22 @@ func (h *GitModHandler) Remove(ctx *HandlerContext, mod *types.Mod) error {

return ctx.Repo.Delete(mod.ID)
}

func (h *GitModHandler) CheckUpdate(ctx *HandlerContext, mod *types.Mod) (bool, error) {
rem := git.NewRemote(memory.NewStorage(), &config.RemoteConfig{
Name: "origin",
URLs: []string{mod.URL},
})

refs, err := rem.List(&git.ListOptions{})
if err != nil {
return false, fmt.Errorf("git error: %v", err)
}
for _, ref := range refs {
if ref.Name() == plumbing.ReferenceName(mod.Branch) {
mod.LatestVersion = ref.Hash().String()
}
}

return mod.LatestVersion != mod.Version, nil
}
2 changes: 1 addition & 1 deletion modmanager/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type HandlerContext struct {

type SourceTypeHandler interface {
Create(ctx *HandlerContext, mod *types.Mod) error
Status(ctx *HandlerContext, mod *types.Mod) (*ModStatus, error)
Update(ctx *HandlerContext, mod *types.Mod, version string) error
Remove(ctx *HandlerContext, mod *types.Mod) error
CheckUpdate(ctx *HandlerContext, mod *types.Mod) (bool, error)
}
28 changes: 28 additions & 0 deletions modmanager/updates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package modmanager

import (
"fmt"
)

func (m *ModManager) CheckUpdates() error {
mods, err := m.repo.GetAll()
if err != nil {
return fmt.Errorf("get all mods failed: %v", err)
}

for _, mod := range mods {
h := m.handlers[mod.SourceType]
updated, err := h.CheckUpdate(m.handlercontext, mod)
if err != nil {
return fmt.Errorf("update check failed for mod '%s': %v", mod.Name, err)
}
if updated {
err = m.repo.Update(mod)
if err != nil {
return fmt.Errorf("failed to update mod-data for '%s': %v", mod.Name, err)
}
}
}

return nil
}
8 changes: 8 additions & 0 deletions public/js/api/mods.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ export const create_mod = mod => protected_fetch("api/mods", {
body: JSON.stringify(mod)
});

export const update_mod = (mod, version) => protected_fetch(`api/mods/${mod.id}/update/${version}`, {
method: "POST"
});

export const check_updates = mod => protected_fetch("api/mods/checkupdates", {
method: "POST"
});

export const remove_mod = id => fetch(`api/mods/${id}`, {method: "DELETE"});
33 changes: 24 additions & 9 deletions public/js/components/pages/mods/Mods.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { add, remove, get_all, is_busy, get_git_mod } from '../../../service/mods.js';
import { add, remove, get_all, is_busy, get_git_mod, update_mod, check_updates } from '../../../service/mods.js';
import FeedbackButton from '../../FeedbackButton.js';
import DefaultLayout from '../../layouts/DefaultLayout.js';
import CDBPackageLink from '../../CDBPackageLink.js';
Expand Down Expand Up @@ -45,9 +45,11 @@ export default {
branch: "refs/heads/master"
});
},
update_mod: update_mod,
remove: remove,
get_mods: get_all,
get_git_mod: get_git_mod
get_git_mod: get_git_mod,
check_updates: check_updates
},
computed: {
busy: is_busy
Expand All @@ -71,6 +73,15 @@ export default {
</div>
</div>
</div>
<div class="row">
<div class="col-10"></div>
<div class="col-2">
<button class="btn btn-primary w-100" v-on:click="check_updates" :disabled="busy">
<i class="fa fa-refresh"></i>
Check for updates
</button>
</div>
</div>
<table class="table table-condensed table-striped">
<thead>
<tr>
Expand All @@ -79,6 +90,7 @@ export default {
<th>Source-Type</th>
<th>Source</th>
<th>Version</th>
<th>Latest Version</th>
<th>Auto-update</th>
<th>Actions</th>
</tr>
Expand Down Expand Up @@ -135,7 +147,7 @@ export default {
</router-link>
</td>
</tr>
<tr v-for="mod in get_mods()">
<tr v-for="mod in get_mods()" :key="mod.id">
<td>
<span class="badge bg-secondary">{{mod.mod_type}}</span>
</td>
Expand All @@ -156,6 +168,9 @@ export default {
<td>
<span class="badge bg-secondary" v-if="mod.version">{{mod.version}}</span>
</td>
<td>
<span class="badge bg-secondary" v-if="mod.latest_version">{{mod.latest_version}}</span>
</td>
<td>
<a class="btn btn-success" v-if="mod.auto_update">
<i class="fa fa-check"></i>
Expand All @@ -168,14 +183,14 @@ export default {
</td>
<td>
<div class="btn-group">
<a class="btn btn-primary">
<i class="fa fa-edit"></i>
Edit
</a>
<a class="btn btn-danger" v-on:click="remove(mod.id)">
<button class="btn btn-primary" v-on:click="update_mod(mod, mod.latest_version)" :disabled="mod.version == mod.latest_version">
<i class="fa fa-download"></i>
Update
</button>
<button class="btn btn-danger" v-on:click="remove(mod.id)">
<i class="fa fa-trash"></i>
Remove
</a>
</button>
</div>
</td>
</tr>
Expand Down
Loading

0 comments on commit fc799c8

Please sign in to comment.