feat: enable changelog generation in release workflow #2

Merged
jamie merged 5 commits from v1.1.0 into main 2026-06-09 14:53:28 +01:00
6 changed files with 57 additions and 14 deletions
Showing only changes of commit eb87e74720 - Show all commits
+11 -11
View File
@@ -167,7 +167,7 @@ func (a *App) Delete(connId, path string) error {
return exp.Delete(path)
}
func (a *App) QueueTransfer(id string, srcConnId, dstConnId, srcPath, dstPath, filename string, size int64, verify bool) error {
func (a *App) QueueTransfer(id string, srcConnId, dstConnId, srcPath, dstPath, filename string, size int64, verify bool, limitMBps int) error {
srcExp, err := a.getExplorerForConnection(srcConnId)
if err != nil {
return err
@@ -185,7 +185,7 @@ func (a *App) QueueTransfer(id string, srcConnId, dstConnId, srcPath, dstPath, f
return err
}
return a.transferManager.QueueTransfer(id, srcPath, dstPath, filename, size, srcExp, dstExp, verify)
return a.transferManager.QueueTransfer(id, srcPath, dstPath, filename, size, srcExp, dstExp, verify, limitMBps)
}
func (a *App) GetTransfers() []*transfer.Transfer {
@@ -232,7 +232,7 @@ func (a *App) PromptUploadFiles(connId, destPath string) error {
remotePath = destPath + fileName
}
a.QueueTransfer(id, "local", connId, localPath, remotePath, fileName, stat.Size(), false)
a.QueueTransfer(id, "local", connId, localPath, remotePath, fileName, stat.Size(), false, 0)
}
return nil
}
@@ -272,7 +272,7 @@ func (a *App) PromptUploadDirectory(connId, destPath string) error {
}
id := uuid.New().String()
a.QueueTransfer(id, "local", connId, path, remotePath, info.Name(), info.Size(), false)
a.QueueTransfer(id, "local", connId, path, remotePath, info.Name(), info.Size(), false, 0)
return nil
})
}
@@ -304,7 +304,7 @@ func (a *App) PromptDownload(connId, remotePath string) error {
size = stat.Size
}
return a.QueueTransfer(id, connId, "local", remotePath, localPath, fileName, size, false)
return a.QueueTransfer(id, connId, "local", remotePath, localPath, fileName, size, false, 0)
}
type TransferItem struct {
@@ -314,7 +314,7 @@ type TransferItem struct {
Size int64 `json:"size"`
}
func (a *App) TransferItems(srcConnId, dstConnId, dstPath string, items []TransferItem, verify bool) error {
func (a *App) TransferItems(srcConnId, dstConnId, dstPath string, items []TransferItem, verify bool, limitMBps int) error {
for _, item := range items {
if !item.IsDir {
id := uuid.New().String()
@@ -328,18 +328,18 @@ func (a *App) TransferItems(srcConnId, dstConnId, dstPath string, items []Transf
remotePath = dstPath + item.Name
}
if err := a.QueueTransfer(id, srcConnId, dstConnId, item.Path, remotePath, item.Name, item.Size, verify); err != nil {
if err := a.QueueTransfer(id, srcConnId, dstConnId, item.Path, remotePath, item.Name, item.Size, verify, limitMBps); err != nil {
return err
}
} else {
// Run remote walk in goroutine to not block UI
go a.transferRemoteDirectory(srcConnId, dstConnId, item.Path, dstPath, verify)
go a.transferRemoteDirectory(srcConnId, dstConnId, item.Path, dstPath, verify, limitMBps)
}
}
return nil
}
func (a *App) transferRemoteDirectory(srcConnId, dstConnId, srcDirPath, dstBasePath string, verify bool) {
func (a *App) transferRemoteDirectory(srcConnId, dstConnId, srcDirPath, dstBasePath string, verify bool, limitMBps int) {
baseName := filepath.Base(srcDirPath)
newDstPath := dstBasePath
@@ -360,11 +360,11 @@ func (a *App) transferRemoteDirectory(srcConnId, dstConnId, srcDirPath, dstBaseP
for _, entry := range entries {
if entry.IsDir {
a.transferRemoteDirectory(srcConnId, dstConnId, entry.Path, newDstPath, verify)
a.transferRemoteDirectory(srcConnId, dstConnId, entry.Path, newDstPath, verify, limitMBps)
} else {
id := uuid.New().String()
itemDstPath := newDstPath + "/" + entry.Name
a.QueueTransfer(id, srcConnId, dstConnId, entry.Path, itemDstPath, entry.Name, entry.Size, verify)
a.QueueTransfer(id, srcConnId, dstConnId, entry.Path, itemDstPath, entry.Name, entry.Size, verify, limitMBps)
}
}
}
+6
View File
@@ -185,6 +185,12 @@
</label>
</div>
<div class="form-group" style="display: flex; align-items: center; gap: 0.5rem; flex-direction: row; margin-bottom: 1.5rem;">
<label style="margin: 0; width: 120px;">Max Speed (MB/s)</label>
<input type="number" id="transfer-limit" value="0" min="0" style="width: 80px;">
<span style="font-size: 0.75rem; color: var(--text-secondary);">(0 = Unlimited)</span>
</div>
<div style="display: flex; justify-content: flex-end; gap: 1rem;">
<button class="btn" style="background: transparent; color: var(--text-primary); border-color: var(--border);" onclick="closeTransferModal()">Cancel</button>
<button class="btn btn-primary" onclick="executeTransfer()">Transfer Here</button>
+4 -1
View File
@@ -529,6 +529,7 @@ window.openTransferModal = () => {
window.closeTransferModal = () => {
document.getElementById('transfer-modal').style.display = 'none';
document.getElementById('transfer-verify').checked = false;
document.getElementById('transfer-limit').value = "0";
};
window.loadTransferDestRoot = () => {
@@ -583,7 +584,9 @@ window.loadTransferDestDirectory = async (connId, path) => {
window.executeTransfer = async () => {
if (selectedItems.length === 0) return;
try {
await TransferItems(currentConn, transferDestConn, transferDestPath, selectedItems);
const verify = document.getElementById('transfer-verify').checked;
const limit = parseInt(document.getElementById('transfer-limit').value, 10) || 0;
await TransferItems(currentConn, transferDestConn, transferDestPath, selectedItems, verify, limit);
closeTransferModal();
showTransfers();
selectedItems = [];
+1
View File
@@ -64,6 +64,7 @@ require (
golang.org/x/net v0.55.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/text v0.38.0 // indirect
golang.org/x/time v0.15.0 // indirect
)
// replace github.com/wailsapp/wails/v2 v2.12.0 => /home/jamie/go/pkg/mod
+2
View File
@@ -148,6 +148,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+33 -2
View File
@@ -1,6 +1,7 @@
package transfer
import (
"context"
"crypto/md5"
"encoding/hex"
"errors"
@@ -10,6 +11,8 @@ import (
"sync"
"time"
"golang.org/x/time/rate"
"goexplore/internal/explorer"
)
@@ -34,6 +37,7 @@ type Transfer struct {
Status Status `json:"status"`
Error string `json:"error,omitempty"`
Verify bool `json:"verify"`
LimitMBps int `json:"limit_mbps"`
srcExp explorer.Explorer
dstExp explorer.Explorer
@@ -89,8 +93,19 @@ func (m *Manager) doTransfer(t *Transfer) error {
hash := md5.New()
tr := io.TeeReader(r, hash)
pr := &progressReader{
var streamReader io.Reader = tr
if t.LimitMBps > 0 {
limitBytes := t.LimitMBps * 1024 * 1024
// Set burst to limitBytes to allow typical io.Copy chunk sizes without erroring
limiter := rate.NewLimiter(rate.Limit(limitBytes), limitBytes)
streamReader = &throttledReader{
r: tr,
limiter: limiter,
}
}
pr := &progressReader{
r: streamReader,
t: t,
}
@@ -118,6 +133,21 @@ func (m *Manager) doTransfer(t *Transfer) error {
return nil
}
type throttledReader struct {
r io.Reader
limiter *rate.Limiter
}
func (tr *throttledReader) Read(p []byte) (int, error) {
n, err := tr.r.Read(p)
if n > 0 && tr.limiter != nil {
if errWait := tr.limiter.WaitN(context.Background(), n); errWait != nil {
return n, errWait
}
}
return n, err
}
type progressReader struct {
r io.Reader
t *Transfer
@@ -138,7 +168,7 @@ func (pr *progressReader) Read(p []byte) (int, error) {
return n, err
}
func (m *Manager) QueueTransfer(id, srcPath, dstPath, filename string, size int64, srcExp, dstExp explorer.Explorer, verify bool) error {
func (m *Manager) QueueTransfer(id, srcPath, dstPath, filename string, size int64, srcExp, dstExp explorer.Explorer, verify bool, limitMBps int) error {
if srcExp == nil || dstExp == nil {
return errors.New("invalid explorers")
}
@@ -151,6 +181,7 @@ func (m *Manager) QueueTransfer(id, srcPath, dstPath, filename string, size int6
BytesTotal: size,
Status: StatusQueued,
Verify: verify,
LimitMBps: limitMBps,
srcExp: srcExp,
dstExp: dstExp,
}