427 Commits

Author SHA1 Message Date
Julio López
d1bc68ef61 refactor(general): cleanup nits (#5236)
Cleanup nits:
- get error handling policy upfront and improve readability in uploader
- update error message
- update field documentation and update flag description
- remove unused function
- const `isWindows` and remove redundant condition check
- add `getEnvVarBool` helper
- refactor common helper for mockfs.AddError* functions, and
  add mockfs.AddErrorEntry<Type> wrappers for clarity.
- removed list of skipped tests from gotestsum summary
2026-03-23 11:52:29 -07:00
Baixiaochun
df247ecf92 fix(snapshots): ErrorEntry policy resolution to use child policy (#5234)
Fix ErrorEntry child policy resolution, includes tests.

- Fixes kopia/kopia#5232
2026-03-20 17:05:51 -07:00
Julio López
4fe60817a0 fix(snapshots): inaccessible entry causes parent directory to be skipped (#5217)
Revert "feat(snapshots): localfs support for passing options (#5044)"
commit c8c4615595.

Fix: return `ErrorEntry` for permission denied instead of aborting

When iterating a directory, if `lstat` fails with permission denied on
an entry, return an `ErrorEntry` instead of an error that stops the
entire directory iteration.

Previously, a single inaccessible entry, such as, a FUSE/sshfs mount
owned by another user, would cause the entire containing directory to
fail and be omitted from the snapshot, resulting in data loss.

Now, the inaccessible entry is returned as an ErrorEntry which is
handled according to the configured error handling policy, allowing
iteration to continue and the rest of the directory to be backed up.

- Fixes: #5045

Differentiate entry type when ignoring failed entries
Fix tests for new behavior, including handling timing-dependent
behavior when snapshots --fail-fast

---------

Co-authored-by: Geoffrey D. Bennett <g@netcraft.com.au>
2026-03-19 12:24:38 -07:00
Julio López
873a89a08d refactor(general): move SafeLongFilename to ospath (#5227)
- Move MaybePrefixLongFilenameOnWindows to ospath package and rename
  it to SafeLongFilename, along with corresponding test.
- Elide the function implementation at build time on non-Windows
  platforms.
- Update documentation and comments for clarity.
- Rename package-local helper function.
2026-03-17 17:43:08 -07:00
Julio López
d81ac7bb7f chore(ci): remove ineffective omitempty tags (#5037) 2025-12-01 20:54:05 -08:00
Julio López
4526f031bf fix(ui): revert omitzero changes (#5035)
- Revert "chore(ci): enable modernize:omitzero linter setting (#4981)"
   reverts 06845c750b
- Revert "refactor(general): omitzero JSON tag in policy structs (#4910)"
  reverts 033b4b1d5e
- Revert "refactor(general): `omitzero` JSON tag (#4907)"
   reverts 5bc467e2ca
- Ref: #5006
2025-11-24 19:18:33 -08:00
Julio Lopez
b723b8e9e4 fix(app): serialize empty Manifest.Stats field (#5029)
- Fixes #5006
2025-11-24 04:54:55 +00:00
Julio Lopez
7db061ee71 build(deps): Go 1.25 (#4987)
Upgrade to Go 1.25
Leverage `WaitGroup.Go` in Go 1.25
2025-11-17 16:42:12 -08:00
Julio Lopez
70f8d678d0 fix(general): handle errors closing writable descriptors (#4998) 2025-11-16 23:07:51 -08:00
Julio Lopez
bb20d9e11a chore(ci): enable wsl_v5:{assign,expr} linter settings (#4982)
Enable wsl_v5 settings:
- assign
- expr
2025-11-12 23:12:06 -08:00
lyndon-li
157c80e5e7 feat(snapshots): Flush after restoring each file (#4825)
Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
2025-11-12 20:59:56 -08:00
Julio Lopez
06845c750b chore(ci): enable modernize:omitzero linter setting (#4981) 2025-11-12 20:54:03 -08:00
Julio Lopez
033b4b1d5e refactor(general): omitzero JSON tag in policy structs (#4910)
The `omitempty` JSON tag is ineffective on fields of struct type, among others.

The fields with tags changed from `omitempty` to `omitzero` can be classified into 2 categories:
- fields for which the intent was to avoid serializing the value when it was zero or empty (such as structs with the zero value for the struct);
- policy-definition fields that have the `omitempty` to match the corresponding policy fields.

The fields are changed such that
- the fields are not serialized when they have the zero (or empty) value; and
- consistency is maintained between policy fields and the corresponding policy definition fields.

---

In the context of policy definitions:

**Fields of type `struct`**:
In some cases, the fields in the policy definition and values are of type struct, such as is the case for the `policy.Policy` and `policy.Definition` structs.
In these cases, the `omitzero` JSON tag avoids marshaling empty fields, making the serialized representation more compact and less noisy, while preserving the same behavior and thus semantic when unmarshaling omitted fields.

**Fields of pointer types**:
The `omitempty` and `omitzero` have _practically_ the same effect on fields of pointer types:
- the field is omitted when it is null
- the field is included when it is not null, even if the value that it points to is "the zero value" for the non-pointer type.

Note: when the pointer type defines an `IsZero()` member function, then that field would also be omitted during marshaling. There are no defined `IsZero()` function for these pointers, so
the semantics are preserved in this case.

The `omitzero` JSON tag in the fields definition structs, such as the `ActionPolicyDefinition struct`, does not change the semantics, it simply makes the marshaled representation more compact.

**Fields of type slice**:
The behavior for `omitempty` and `omitzero` differs for slices, and maps as well.

The struct fields of slice type, such as `[]string`, are left with the `omitempty` tag to be able to tell the difference between a nil slice and a non-nil, zero-length slice. Even though, currently most code paths do not explicitly differentiate between a nil slice and an empty slice, the `omitempty` tag is left unmodified out of abundance of caution.

---

Ref:

- #4973
- #4907
2025-11-12 18:33:30 -08:00
Nathan Baulch
657fda216a chore(ci): upgrade to golangci-lint 2.6.1 (#4973)
- upgrade to golangci-lint 2.6.1
- updates for gosec
- updates for govet
- updates for perfsprint
- updates modernize

Leaves out modernize:omitempty due to conflicts with tests
2025-11-11 21:27:10 -08:00
Nathan Baulch
557940c524 chore(ci): upgrade to golangci-lint v2.5.0 (#4931)
Upgrades golangci-lint to v2.5.0

Enables:
- wsl_v5

Disables:
- embeddedstructfieldcheck
- noinlineerr (not used in this codebase)
- noctx (temporarily)
- godot
- wsl (deprecated)

Co-authored-by: Julio Lopez <1953782+julio-lopez@users.noreply.github.com>
2025-11-11 12:37:07 -08:00
lyndon-li
7114e991c6 feat(general): add stats to maintenance run - SnapshotGC (#4964)
* snapshot gc stats

Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
2025-11-10 16:28:43 -08:00
Julio Lopez
069018adca refactor(general): use explicit return values (#4940)
Add return values in long helper function. This Improves clarity
and avoids 'naked' return and removes `//nolint:nakedret` annotation.

Explicit return values for GetShardedPathAndFilePath
2025-10-30 23:14:58 -07:00
Julio Lopez
356930b1a9 refactor(general): simplify function and generics signatures (#4930) 2025-10-29 12:32:51 -07:00
Julio Lopez
22f0919644 refactor(general): simplify construction of error messages (#4913) 2025-10-24 13:45:42 -07:00
Julio Lopez
d8519ab9fa refactor(test): run cases as sub-tests (#4912) 2025-10-24 12:40:45 -07:00
Julio Lopez
5bc467e2ca refactor(general): omitzero JSON tag (#4907)
* remove omitempty from object id fields
* remove omitempty from storage stats fields
* use omitzero for other structs

* remove `omitempty` from `UpgradeLockIntent` fields

The `omitempty` JSON tag is ineffective for fields of 
type `Time` and `Duration`.
Also, this struct is only used during the "upgrade"
protocol, and it is OK to explicitly serialize 0 values,
as it was done before.
2025-10-23 22:59:52 -07:00
Julio Lopez
995e7fd893 refactor(general): modernize (#4903)
Applies the modernize changes for the following categories:

- mapsloop
- stringsseq
- stringscutprefix
- sortslice
2025-10-23 17:11:38 -07:00
lyndon-li
657db9706b feat(general): interfaces and structures for maintenance stats (#4890)
Maintenance is critical for healthy of the repository.

On the other hand, Maintenance is complex, because
it runs multiple sub tasks each may generate different
results according to the maintenance policy.
The results may include deleting/combining/adding
data/metadata to the repository.

It is worthy to add more observability for these
tasks for below reasons:

It is helpful for troubleshooting. Any data change
to the repository is critical, the observability info
helps to understand what happened during the
maintenance and why that happened.

It is helpful for users to understand/predict the
repo's behavior. The repo data may be stored
in a public cloud for which costs are sensitive
to scale/duration of data stored. On the other
hand, repository has its own policy to manage
the data, so the data is not deleted until it is
safe enough according to the policy.

The observability info helps users to
understand how much data is in-use,
how much data is out of use and
when it is deleted
2025-10-22 18:14:10 -07:00
Jarek Kowalski
0f7253eb66 feat(general): rewrote content logs to always be JSON-based and reorganized log structure (#4822)
This is a breaking change to users who might be using Kopia as a library.

### Log Format

```json
{"t":"<timestamp-rfc-3389-microseconds>", "span:T1":"V1", "span:T2":"V2", "n":"<source>", "m":"<message>", /*parameters*/}
```

Where each record is associated with one or more spans that describe its scope:

* `"span:client": "<hash-of-username@hostname>"`
* `"span:repo": "<random>"` - random identifier of a repository connection (from `repo.Open`)
* `"span:maintenance": "<random>"` - random identifier of a maintenance session
* `"span:upload": "<hash-of-username@host:/path>"` - uniquely identifies upload session of a given directory
* `"span:checkpoint": "<random>"` - encapsulates each checkpoint operation during Upload
* `"span:server-session": "<random>"` -single client connection to the server
* `"span:flush": "<random>"` - encapsulates each Flush session
* `"span:maintenance": "<random>"` - encapsulates each maintenance operation
* `"span:loadIndex" : "<random>"` - encapsulates index loading operation
* `"span:emr" : "<random>"` - encapsulates epoch manager refresh
* `"span:writePack": "<pack-blob-ID>"` - encapsulates pack blob preparation and writing

(plus additional minor spans for various phases of the maintenance).

Notable points:

- Used internal zero allocation JSON writer for reduced memory usage.
- renamed `--disable-internal-log` to `--disable-repository-log` (controls saving blobs to repository)
- added `--disable-content-log` (controls writing of `content-log` files)
- all storage operations are also logged in a structural way and associated with the corresponding spans.
- all content IDs are logged in a truncated format (since first N bytes that are usually enough to be unique) to improve compressibility of logs (blob IDs are frequently repeated but content IDs usually appear just once).

This format should make it possible to recreate the journey of any single content throughout pack blobs, indexes and compaction events.
2025-09-27 17:11:13 -07:00
Julio Lopez
9a42e9b8a5 refactor(general): miscellaneous cleanups (#4774)
Nits and cleanups:
- clarify log message to indicate the effect of advancing the deletion watermark;
- add omitzero JSON tag to appropriate fields in snapshot.Manifest struct;
- use maps.Clone instead of explicit loop;
- rename function to IterateUnreferencedPacks for clarity;
- use atomic.Int32 type;
- move a continue check to the beginning of the loop, no actual
  work / side effects were performed before the check;
- reduce type requirement in blob.ReadBlobMap
2025-08-20 17:49:00 -07:00
Ankit Jain
35089a4894 feat(restore): added support for deleting extra files in restore path (#4725) 2025-07-17 07:10:32 +00:00
Julio Lopez
ae8d7c3ed4 refactor(general): use require to cleanup snapshot tests (#4708) 2025-07-01 19:01:59 -07:00
Julio Lopez
fc7a3c36b4 fix(general): use snapshot end time as tie breaker for equal start time (#4705)
- use snapshot end time as tie breaker for equal start time
- pass prototype snapshot manifest in uploader
- remove -1 ns hack for checkpoints and fix corresponding test
- test snapshot.SortByTime
2025-07-01 18:06:02 -07:00
Julio Lopez
89d1bbc743 chore(general): minor cleanups (#4704)
- use `slices.Clone`
- remove stale `.gometalinter.json`
- unexport `maintenance.dropDeletedContents`
- rename `fetchIndexBlob`
- use `require` in `TestTimeFuncWiring`
2025-07-01 12:05:50 -07:00
Nick
ed304e6c12 feat(snapshots): Add periodic JSON progress output to snapshot verify (#4645)
- Add read stats to snapshot verifier output
- Add periodic JSON progress output.
- Refactor the use of directory summary.
- Use stats mutex for all stats.
- Add processedBytes to the snapshot verify output
- Output more frequently, when bytes processed changes
2025-06-24 15:15:59 -07:00
Nick
b2b051417f Add JSON output flag for snapshot verify (#4644) 2025-06-24 13:20:09 -07:00
Julio Lopez
735adfcf85 refactor(general): small misc. cleanups (#4666)
* remove unnecessary type argument
* modernize with max
* unexport getPartial and update comment
* unexport getFull
* verifyNotCached helper
* use require helpers
* leverage verify[Not]Cached
* use windowsOSName const
* fix comment wrapping
* require in stat_test
* use 512 as the write size and log allocated size
* rename const to expectedMinAllocSize
* write a single byte to test file
* add TestGetBlockSizeFromCurrentFS
* require Positive
* log before invariant check
2025-06-13 23:56:37 -07:00
Nathan Baulch
19d92613a6 chore(general): typos (#4659) 2025-06-10 17:24:14 -07:00
Julio Lopez
e1d065aee1 refactor(general): misc cleanups (#4652)
- use raw strings for readability, removes escaping
- clarify comment
- add self-documenting message to test assertion
- always cleanup test file
- refactor(test): cleanup TestParseSnapListAllExeTest
- nit: call getLogOutputPrefix once
- rename SkipTestUnlessLinux
- inline TestSkipUnlessCI
- rename SkipTestOnCIUnlessLinuxAMD64
2025-06-04 22:58:01 -07:00
Julio Lopez
d91a5a8f94 chore(general): enable forcetypeassert linter (#4624)
- enable `forcetypeassert` linter in non-test files
- add `//nolint` annotations
- add `testutil.EnsureType` helper for type assertions
- enable `forcetypeassert` linter in test files
2025-05-31 23:17:38 -07:00
Julio Lopez
d5f23be119 refactor(general): minor cleanups (#4621)
- add assertion messages to help troubleshooting upload tests.
- fix typo
- fix debug log message
2025-05-30 23:06:53 -07:00
Julio Lopez
3f01b0c578 refactor(general): upload tests (#4619)
- use 'require/assert'
- refactor TestUploadMetadataCompression as a table test
- allow tests to run in parallel
- use t.Cleanup and add a missing cleanup
- use maps.Clone
2025-05-30 10:22:06 -07:00
Julio Lopez
afc635c9c3 refactor(general): minor cleanups in snapshot GC (#4612)
Cleanups in snapshot GC:
- add findUnreferencedAndRepairRereferenced
- moves logging from snapshotgc.Run to findUnreferencedAndRepairRereferenced
- removes returning collected stats, simplifies signature
- simplifies caller (snapshotgc.Run)
- removes now unused snapshotgc.Stats

Changes in behavior:
- logs before flushing to get info even if flush fails
- new: logs undeleted content stats
2025-05-29 07:46:43 -07:00
Jarek Kowalski
dc1342e117 fix(snapshots): completely ignore unsupported entries instead of reporting them as ignored errors to avoid snapshot warnings (#4613) 2025-05-29 06:53:50 -07:00
Julio Lopez
3d4c5f8f9e refactor(general): s/interface{}/any/ (#4614) 2025-05-29 06:07:49 +00:00
shniubobo
dd664b5554 fix(snapshots): Remove checkpoints after a complete snapshot (#4439)
* fix(snapshots): Remove checkpoints after a complete snapshot

... by setting start time of checkpoints one nanosecond earlier than
that of the snapshot.

* test(snapshots): Test for leftover checkpoints

* fix linter issues

* removed stray curly brace

---------

Co-authored-by: Jarek Kowalski <jaak@jkowalski.net>
2025-05-24 15:10:40 +00:00
Rohit-BM18
dbf5bacdc8 feat(cli): helper functions to get preceding snapshots for diff (#4559)
Add helper functions and relevant tests for fetching previous snapshot manifests
2025-05-13 04:14:33 +00:00
Julio Lopez
562b81a28d fix(general): avoid removing error cause (#4536)
Credit:  @alexvbg  Aleksandr Samarin <alexvbg@users.noreply.github.com>

Authored-by: Aleksandr Samarin <alexvbg@users.noreply.github.com>
2025-04-30 00:04:07 -07:00
Julio Lopez
8098f49c90 chore(ci): remove exclusion for unused ctx parameters (#4530)
Remove unused-parameter exclusion for `ctx` in revive linter.

---------

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
Co-authored-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-04-26 23:11:36 -07:00
Matthieu MOREL
8a176255c0 fix(general): enable wsl for all go files (#4524)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-04-26 13:01:20 -07:00
Matthieu MOREL
675e958877 chore(ci): bump golangci-lint to v2.1.2 (#4500)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-04-15 22:49:13 -07:00
Jarek Kowalski
51ef01dad5 refactor(snapshots): extracted snapshot.FindPreviousManifests() (#4453) 2025-04-13 04:08:03 +00:00
alingse
e0d3fc0fa5 fix(general): use correct error in call to errors.Wrap (#4477)
use `twerr` instead of `err`, which is always `nil`
2025-03-29 23:08:55 -07:00
Jarek Kowalski
51de24dcff refactor(snapshots): refactored uploader into separate package (#4450) 2025-03-14 15:48:31 -07:00
Nick
77448b7379 Account for symlinks in directory summary (#4421)
Account for symlinks in directory summary
2025-02-20 19:56:11 -08:00