# RFC: Freeze package versions

**URL:** https://discourse.julialang.org/t/rfc-freeze-package-versions/105795
**Category:** General Usage
**Tags:** package, pkg
**Created:** [November 4, 2023, 2:49pm UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795 "2023-11-04T14:49:59Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [November 4, 2023, 2:49pm UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795/1 "2023-11-04T14:49:59Z")

</div>

I wrote the following function freeze():

```julia
# freeze the current package versions; overwrites the current Project.toml file
using Pkg, TOML
"""
    freeze()

Freezes the current package versions by adding them to the Project.toml file.
"""

function freeze()
    project_file, compat = project_compat()
    deps = (TOML.parsefile(project_file))["deps"]
    open(project_file, "w") do io
        println(io, "[deps]")
        TOML.print(io, deps)
        println(io)
        println(io, "[compat]")
        TOML.print(io, compat)
    end
    nothing
end

"""
    project_compat()

Create a dictionary of package dependencies and their current versions.

Returns the full file name of the Project.toml file and the dictionary
`compat` that can be added to the Project.toml file to freeze the package
versions.
"""
function project_compat()
    io = IOBuffer();
    Pkg.status(; io)
    st = String(take!(io))
    i = 1
    project_file=""
    compat = Dict{String, Any}()
    for line in eachline(IOBuffer(st))
        if i == 1
            project_file=line
        else
            pkg_vers = split(line, "] ")[2]
            pkg = split(pkg_vers, " v")[1]
            vers = split(pkg_vers, " v")[2]
            push!(compat, (String(pkg)=>String("~"*vers)))
        end
        i += 1
    end
    project_file = expanduser(split(project_file,'`')[2])
    project_file, compat
end

```

The idea is to fix the current versions of the project dependencies and to commit the generated `Project.toml` file to git. Compared to committing the `Manifest.toml` this has the following advantages:

- the project stays compatible with different Julia versions
- changes in the git log are readable (I find the Manifest.toml file unreadable, YMMV)

I might make this more robust, add some options and create a package out of it.

What do you think about this idea?

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [November 5, 2023, 1:18am UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795/2 "2023-11-05T01:18:09Z")

</div>

Just note that it only “freezes” direct dependency versions, indirect deps versions can become different.

Also

> [@ufechner7](#):
>
> - the project stays compatible with different Julia versions

this part is only different to Manifest compatibility because here you don’t fix indirect deps versions. So, Manifest breaks on Julia update when the required version of **any** dependency is not compatible with new Julia – and your Project.toml breaks when the version of any **direct** dep is not compatible with new Julia.

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [November 5, 2023, 4:27am UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795/3 "2023-11-05T04:27:14Z")

</div>

> [@aplavin](#):
>
> your Project.toml breaks when the version of any **direct** dep is not compatible with new Julia.

I have not seen this yet in practice, at least not when going from 1.9 to 1.10 …

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [November 5, 2023, 12:07pm UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795/4 "2023-11-05T12:07:37Z")

</div>

With transitive deps fixed some breakage happens very often, almost on every minor julia version. Of course it will be less of an issue with fixing direct deps only.  
It’s a compromise: fix all dependency versions (Manifest) vs allow any version of indirect deps (Project + strict compat).

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [November 5, 2023, 2:08pm UTC](https://discourse.julialang.org/t/rfc-freeze-package-versions/105795/5 "2023-11-05T14:08:40Z")

</div>

I created a package that provides the function freeze, improved version compared to the version I posted here. Have a look:

> **[GitHub - ufechner7/PkgHelpers.jl: Helper functions for the Julia package manager](https://github.com/ufechner7/PkgHelpers.jl)**
>
> Helper functions for the Julia package manager. Contribute to ufechner7/PkgHelpers.jl development by creating an account on GitHub.

Usage is explained in the README.md .

Feel free to test it and create issues if you find a bug or miss a feature.
