Skip to content

Commit f658ad6

Browse files
committed
Change ActiveLinkStyle to return the folder instead of link
Soft links are not like hard links or folders. Sometimes, they are treated differently by the operating system (and Julia). As a result, for some operations, an extra step is required to work with the output produced by the ActiveStyle in OutputPathGenerator. This PR changes the returned path to be the newly created folder instead of the link. The link is still being created and managed, which means that users can still assume that their output can always be found in `output_active`, but the path that is presented to Julia code that uses `OutputPathGenerator` is now the path of the newly created folder. This has the advantage that the path is a normal folder, possibly simplifying certain operations.
1 parent cf29dce commit f658ad6

File tree

4 files changed

+44
-27
lines changed

4 files changed

+44
-27
lines changed

NEWS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
ClimaUtilities.jl Release Notes
22
===============================
33

4+
v0.1.8
5+
------
6+
7+
- `generate_output_path(..., ::ActiveLinkStyle)` now returns the folder instead
8+
of the link. Links are still being created and managed. PR
9+
[#63](https://github.com/CliMA/ClimaUtilities.jl/pull/63)
10+
411
v0.1.7
512
------
613

@@ -24,3 +31,5 @@ v0.1.3
2431
-------
2532
- Add `DataStructures` module containing `LRUCache` object. PR [#35](https://github.com/CliMA/ClimaUtilities.jl/pull/35)
2633
- Add `OutputPathGenerator`. PR [#28](https://github.com/CliMA/ClimaLand.jl/pull/28)
34+
35+
[badge-💥breaking]: https://img.shields.io/badge/💥BREAKING-red.svg

docs/src/outputpathgenerator.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ results.
4242

4343
Let's assume your `output_path` is set to `data`.
4444

45-
* If `data` doesn't exist, the module creates it and returns
46-
`data/output_active`. This link points to the newly created subfolder
47-
`data/output_0000`.
48-
* If `data` exists and contains an `output_active` link pointing to
49-
`data/output_0005`, the module creates a new subfolder `data/output_0006` and
50-
updates `output_active` to point to it.
45+
* If `data` doesn't exist, the module creates it and returns `data/output_0000`.
46+
In doing this, a link `data/output_active` to `data/output_0000` is created so
47+
that you can always access your data in `data/output_active`.
48+
* If `data` exists and contains an `output_active` link pointing to
49+
`data/output_0005`, `output_active` is updated to point to a new subfolder
50+
called `data/output_0006`
5151
* If `data` exists with or without an `output_active` link, the module checks
5252
for existing subfolders named `data/output_XXXX` (with `XXXX` a number). If
5353
none are found, it creates `data/output_0000` and a link `data/output_active`
@@ -60,7 +60,6 @@ users, so some details about links might be slightly different depending on your
6060
system. If you are using Windows, please have a look at docstring on the
6161
`ActiveLinkStyle` to learn more about possible differences.
6262

63-
6463
## API
6564

6665
```@docs

src/OutputPathGenerator.jl

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,21 @@ This style is designed to:
6969
- provide a deterministic and fixed path for the latest available data,
7070
- and have nearly zero runtime overhead.
7171
72+
`generate_output_path` returns path to the newly created folder with the next available
73+
increment (of the form `output_1234`), and ensures that a valid `output_active` link points
74+
to that folder.
75+
7276
# Examples:
7377
7478
Let us assume that `output_path = dormouse`.
7579
7680
- `dormouse` does not exist in the current working directory: `ActiveLinkStyle` will create
77-
it and return `dormouse/output_active`. `dormouse/output_active` is a symlink that points
78-
to the newly created `dormouse/output_0000` directory.
81+
it and return `dormouse/output_0000`. In the process, a symlink `dormouse/output_active`
82+
is also created. This symlink points to `dormouse/output_0000`.
7983
- `dormouse` exists and contains a `output_active` link that points to
80-
`dormouse/output_0005`, `ActiveLinkStyle` will a new directory `dormouse/output_0006` and
81-
change the `output_active` to point to this directory.
84+
`dormouse/output_0005`, `ActiveLinkStyle` will a create new directory
85+
`dormouse/output_0006`, return this path, and change the `output_active` to point to this
86+
directory.
8287
- `dormouse` exists and does not contain a `output_active`, `ActiveLinkStyle` will check if
8388
any `dormouse/output_XXXX` exists. If not, it creates `dormouse/output_0000` and a link
8489
`dormouse/output_active` that points to this directory.
@@ -112,13 +117,13 @@ How the output should be structured (in terms of directory tree) is determined b
112117
- `RemovePreexistingStyle`: the `output_path` provided is the actual output path. If a directory
113118
already exists there, remove it without asking for confirmation.
114119
115-
- `ActiveLinkStyle`: the `output_path` provided is `output_path/output_active`, a link to a
116-
subdirectory within `output_path`. This style looks at the content of `output_path` and
117-
adds new subdirectories. The added directories are named with a counter, with the latest
118-
always accessible via the `output_path/output_active` symlink. This is style is
119-
non-destructive.
120+
- `ActiveLinkStyle`: the `output_path` returned is a new folder of the form
121+
`output_path/output_1234`, where the number is incremented every time this function is
122+
called. `ActiveLinkStyle` also creates a link `output_path/output_active` that ensures
123+
that the most recent output is always accessible at the `output_path/output_active` path.
124+
This is style is non-destructive.
120125
121-
(Note, "styles" have nothing to do with traits.)
126+
(Note, "styles" have nothing to do with Julia traits.)
122127
"""
123128
function generate_output_path(
124129
output_path;
@@ -244,7 +249,7 @@ function generate_output_path(::ActiveLinkStyle, output_path; context = nothing)
244249
end
245250
end
246251
maybe_wait_filesystem(context, new_output_folder)
247-
return active_link
252+
return new_output_folder
248253
end
249254

250255
end

test/output_path_generator.jl

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,33 @@ end
6868
# Folder does not yet exist
6969
output_path = joinpath(base_output_path, "dormouse")
7070

71-
expected_output = joinpath(output_path, "output_active")
71+
output_link = joinpath(output_path, "output_active")
72+
73+
expected_output = joinpath(output_path, "output_0000")
7274

7375
@test expected_output ==
7476
generate_output_path(output_path, context = context)
7577

7678
# Check that it exists now
7779
@test isdir(output_path)
7880

79-
# Check folder output_0000 was created
80-
@test isdir(joinpath(output_path, "output_0000"))
81+
# Check link output_active was created
82+
@test islink(output_link)
8183

82-
# Check link points to folder
83-
@test readlink(expected_output) == "output_0000"
84+
# # Check link points to folder
85+
@test readlink(output_link) == "output_0000"
8486

8587
# Now the folder exists, let us see if the rotation works
88+
expected_output = joinpath(output_path, "output_0001")
89+
8690
@test expected_output ==
8791
generate_output_path(output_path, context = context)
8892

89-
# Check folder output_0001 was created
93+
# Check folder was created
9094
@test isdir(joinpath(output_path, "output_0001"))
9195

9296
# Check link points to new folder
93-
@test readlink(expected_output) == "output_0001"
97+
@test readlink(output_link) == "output_0001"
9498

9599
# Now let us check something wrong
96100

@@ -101,7 +105,7 @@ end
101105
ClimaComms.barrier(context)
102106
let_filesystem_catch_up()
103107

104-
output_link = generate_output_path(output_path, context = context)
108+
generate_output_path(output_path, context = context)
105109
@test readlink(output_link) == "output_0002"
106110

107111
ClimaComms.barrier(context)
@@ -119,7 +123,7 @@ end
119123
if ClimaComms.iamroot(context)
120124
wrong_dir = joinpath(output_path, "wrong")
121125
mkdir(wrong_dir)
122-
symlink(wrong_dir, expected_output, dir_target = true)
126+
symlink(wrong_dir, output_link, dir_target = true)
123127
end
124128
ClimaComms.barrier(context)
125129
@test_throws ErrorException generate_output_path(

0 commit comments

Comments
 (0)