├── .github ├── CODEOWNERS ├── label-pr.yml ├── labels.yml └── workflows │ ├── bash.yml │ ├── dockerimage.yml │ ├── label-maker.yml │ ├── labeler.yml │ ├── rust.yml │ └── shell.yml ├── .gitignore ├── .gitpod.Dockerfile ├── .gitpod.yml ├── CODE_OF_CONDUCT.md ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs ├── gui ├── README.md ├── gui.py ├── license └── requirements.txt ├── src ├── detection.rs ├── lib.rs ├── main.rs └── write.rs └── tools └── dockerfreeze /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Reference to configuration - https://github.blog/2017-07-06-introducing-code-owners/ 2 | # Relevant https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 3 | 4 | # This file is used to set permission per team or user to allow auto-merging 5 | 6 | # Maintainers 7 | * @JesterOrNot -------------------------------------------------------------------------------- /.github/label-pr.yml: -------------------------------------------------------------------------------- 1 | # Programming language specific 2 | - regExp: ".*\\.rs+$" 3 | labels: ["rustlang"] 4 | 5 | - regExp: ".*\\.py+$" 6 | labels: ["python"] 7 | 8 | - regExp: ".*\\.c+$" 9 | labels: ["c-lang"] 10 | 11 | - regExp: ".*\\.cpp+$" 12 | labels: ["CPP"] 13 | 14 | - regExp: ".*\\.sh+$" 15 | labels: ["shell"] 16 | 17 | - regExp: ".*\\.bash+$" 18 | labels: ["bash"] 19 | 20 | - regExp: ".*\\.br+$" 21 | labels: ["brainfuck"] 22 | 23 | - regExp: ".*\\.jar+$" 24 | labels: ["java"] 25 | 26 | - regExp: ".*\\.v+$" 27 | labels: ["vlang"] 28 | 29 | - regExp: ".*\\.cs+$" 30 | labels: ["csharp"] 31 | 32 | - regExp: "^/tests/.*" 33 | labels: ["tests"] 34 | 35 | - regExp: "^/benches/.*" 36 | labels: ["benches"] 37 | 38 | - regExp: "^/LICENSE/.*" 39 | labels: ["license"] 40 | 41 | - regExp: ".*\\.md+$" 42 | labels: ["markdown"] 43 | 44 | - regExp: "^(Cargo\\.toml|requirements\\.txt)$" 45 | labels: ["dependencies"] 46 | 47 | # Repository specific 48 | - regExp: "^/docs/.*" 49 | labels: ["docs"] -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # This file handles labels on GitHub 2 | 3 | # MISC 4 | - name: bug 5 | color: d73a4a 6 | description: "Something isn't working" 7 | 8 | - name: question 9 | color: 7300ff 10 | description: "For questions" 11 | 12 | - name: feature-request 13 | color: 03fc5a 14 | description: "Feature requests" 15 | 16 | - name: docs 17 | color: 0075ca 18 | description: "Improvements or additions to documentation" 19 | 20 | - name: duplicate 21 | color: cfd8d7 22 | description: "This issue or pull request already exists" 23 | 24 | - name: enhancement 25 | color: a22eef 26 | description: "Proposal for code improvement" 27 | 28 | - name: license 29 | color: 1a7546 30 | description: "Relevant to licensing" 31 | 32 | - name: dependencies 33 | color: ca0ef0 34 | description: "Relevant to dependencies" 35 | 36 | - name: tests 37 | color: 8d0fd6 38 | description: "Relevant to tests" 39 | 40 | - name: benches 41 | color: cc1250 42 | description: "Relevant to benchmarks" 43 | 44 | # Programming language specific 45 | - name: python 46 | color: 00aeff 47 | description: "Relevant to python" 48 | 49 | - name: rustlang 50 | color: f58142 51 | description: "Relevant to rustlang" 52 | 53 | - name: shell 54 | color: 74e63c 55 | description: "Relevant to shell" 56 | 57 | - name: bash 58 | color: 9dff00 59 | description: "Relevant to bash" -------------------------------------------------------------------------------- /.github/workflows/bash.yml: -------------------------------------------------------------------------------- 1 | name: Bash 2 | 3 | # Relevant to events - https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows 4 | on: 5 | pull_request: 6 | types: [synchronize, opened, reopened, ready_for_review] 7 | paths: 8 | - '**.bash' 9 | - "tools/dockerfreeze" 10 | 11 | jobs: 12 | # Linting 13 | lint: 14 | runs-on: ubuntu-latest 15 | container: debian:stable 16 | steps: 17 | - name: Installing dependencies.. 18 | run: | 19 | # Sync repos 20 | # Check for git 21 | if ! apt list --installed 2>/dev/null | grep -qP "^git\/stable.*"; then 22 | # Check if we can install git 23 | if ! apt list | grep -qP "^git\/stable.*"; then 24 | apt update 25 | elif apt list | grep -qP "^git\/stable.*"; then 26 | true 27 | else 28 | exit 255 29 | fi 30 | # Install git 31 | apt install -y git 32 | elif apt list --installed 2>/dev/null | grep -qP "^git\/stable.*"; then 33 | true 34 | else 35 | exit 255 36 | fi 37 | # Check for shellcheck 38 | if ! apt list --installed 2>/dev/null | grep -qP "^shellcheck\s{1}-.*"; then 39 | # Check if we can install shellcheck 40 | if ! apt list | grep -qP "^shellcheck\s{1}-.*"; then 41 | apt update 42 | elif apt list | grep -qP "^shellcheck\s{1}-.*"; then 43 | true 44 | else 45 | exit 255 46 | fi 47 | # Install shellcheck 48 | apt install -y shellcheck 49 | elif apt list --installed 2>/dev/null | grep -qP "^shellcheck\s{1}-.*"; then 50 | true 51 | else 52 | exit 255 53 | fi 54 | - name: Pulling git dir.. 55 | uses: actions/checkout@v2 56 | - name: Processing files.. 57 | # Make sure that bash is used 58 | shell: bash 59 | run: | 60 | cd "$GITHUB_WORKSPACE" 61 | 62 | # Process files 63 | ## NOTICE: Do not use for loop to avoid pitfall https://mywiki.wooledge.org/BashPitfalls#pf1 64 | git --git-dir="$GITHUB_WORKSPACE/.git" ls-files -z -- '*.bash' tools/dockerfreeze | while IFS= read -rd '' file; do 65 | printf 'linting bash file %s\n' "$file" 66 | shellcheck --external-sources --shell=bash "$file" 67 | done -------------------------------------------------------------------------------- /.github/workflows/dockerimage.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | 7 | build: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Build the Docker image 14 | run: | 15 | cargo install --path . --force 16 | dockerfreeze 17 | docker build . --file Dockerfile --tag my-image-name:$(date +%s) 18 | -------------------------------------------------------------------------------- /.github/workflows/label-maker.yml: -------------------------------------------------------------------------------- 1 | name: ConaIsa 2 | 3 | # Relevant to events - https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows 4 | on: 5 | pull_request: 6 | types: [synchronize, opened, reopened, ready_for_review] 7 | paths: 8 | - '.github/labels.yml' 9 | 10 | jobs: 11 | labeler: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Assigning labels 16 | if: success() 17 | uses: crazy-max/ghaction-github-labeler@v1 18 | with: 19 | yaml_file: .github/labels.yml 20 | skip_delete: false 21 | dry_run: false 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | # Workflow to associate labels automatically 2 | name: Label management 3 | 4 | on: 5 | pull_request: 6 | types: [synchronize, opened, reopened, ready_for_review] 7 | 8 | jobs: 9 | label: 10 | runs-on: ubuntu-latest 11 | steps: 12 | # We need to checkout the repository to access the configured file (.github/label-pr.yml) 13 | - uses: actions/checkout@v2 14 | - name: Labeler 15 | uses: docker://decathlon/pull-request-labeler-action:2.0.0 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | # Here we can override the path for the action configuration. If none is provided, default one is `.github/label-pr.yml` 19 | CONFIG_PATH: ${{ secrets.GITHUB_WORKSPACE }}/.github/label-pr.yml -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Build 13 | run: cargo build --verbose 14 | - name: Run tests 15 | run: cargo test --verbose 16 | -------------------------------------------------------------------------------- /.github/workflows/shell.yml: -------------------------------------------------------------------------------- 1 | name: Shell 2 | 3 | # Relevant to events - https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows 4 | on: 5 | pull_request: 6 | types: [synchronize, opened, reopened, ready_for_review] 7 | paths: 8 | - '**.sh' 9 | 10 | jobs: 11 | # Linting 12 | lint: 13 | runs-on: ubuntu-latest 14 | container: debian:stable 15 | steps: 16 | - name: Installing dependencies.. 17 | run: | 18 | # Sync repos 19 | # Check for git 20 | if ! apt list --installed 2>/dev/null | grep -qP "^git\/stable.*"; then 21 | # Check if we can install git 22 | if ! apt list | grep -qP "^git\/stable.*"; then 23 | apt update 24 | elif apt list | grep -qP "^git\/stable.*"; then 25 | true 26 | else 27 | exit 255 28 | fi 29 | # Install git 30 | apt install -y git 31 | elif apt list --installed 2>/dev/null | grep -qP "^git\/stable.*"; then 32 | true 33 | else 34 | exit 255 35 | fi 36 | # Check for shellcheck 37 | if ! apt list --installed 2>/dev/null | grep -qP "^shellcheck\s{1}-.*"; then 38 | # Check if we can install shellcheck 39 | if ! apt list | grep -qP "^shellcheck\s{1}-.*"; then 40 | apt update 41 | elif apt list | grep -qP "^shellcheck\s{1}-.*"; then 42 | true 43 | else 44 | exit 255 45 | fi 46 | # Install shellcheck 47 | apt install -y shellcheck 48 | elif apt list --installed 2>/dev/null | grep -qP "^shellcheck\s{1}-.*"; then 49 | true 50 | else 51 | exit 255 52 | fi 53 | - name: Pulling git dir.. 54 | uses: actions/checkout@v2 55 | - name: Processing files.. 56 | # Make sure that bash is used 57 | shell: bash 58 | run: | 59 | cd "$GITHUB_WORKSPACE" 60 | 61 | # Process files 62 | ## NOTICE: Do not use for loop to avoid pitfall https://mywiki.wooledge.org/BashPitfalls#pf1 63 | git --git-dir="$GITHUB_WORKSPACE/.git" ls-files -z -- '*.sh' | while IFS= read -rd '' file; do 64 | printf 'linting shell file %s\n' "$file" 65 | shellcheck --external-sources --shell=sh "$file" 66 | done -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full-vnc 2 | 3 | USER gitpod 4 | 5 | RUN brew install tcl-tk 6 | 7 | RUN sudo apt-get update \ 8 | && sudo apt-get install -y \ 9 | shellcheck \ 10 | tk-dev \ 11 | python-tk \ 12 | python3-tk 13 | 14 | RUN npm i -g bash-language-server 15 | 16 | RUN pyenv install 3.6.2 && pyenv global 3.6.2 17 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.Dockerfile 3 | tasks: 4 | - init: | 5 | cargo build 6 | cargo install --path . --force 7 | command: dockerfreeze --help 8 | name: Build Dockerfreeze 9 | - init: | 10 | pip3 install -r gui/requirements.txt 11 | python3 gui/gui.py 12 | name: Build GUI 13 | ports: 14 | - port: 6080 15 | onOpen: ignore 16 | - port: 35900 17 | onOpen: ignore 18 | - port: 5900 19 | onOpen: ignore 20 | vscode: 21 | extensions: 22 | - hbenl.vscode-test-explorer@2.15.0:koqDUMWDPJzELp/hdS/lWw== 23 | - Swellaby.vscode-rust-test-adapter@0.11.0:Xg+YeZZQiVpVUsIkH+uiiw== 24 | - serayuzgur.crates@0.4.7:HMkoguLcXp9M3ud7ac3eIw== 25 | - belfz.search-crates-io@1.2.1:kSLnyrOhXtYPjQpKnMr4eQ== 26 | - bungcip.better-toml@0.3.2:3QfgGxxYtGHfJKQU7H0nEw== 27 | - timonwong.shellcheck@0.9.0:hsU/Rd39aqPYowTqL+DbXg== 28 | - mads-hartmann.bash-ide-vscode@1.4.0:/qx+rdXE/fGTGWhelNf3aQ== 29 | github: 30 | prebuilds: 31 | branches: true 32 | pullRequestsFromForks: true 33 | addComment: true 34 | addLabel: true 35 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at info@gitpod.io. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dockerfreeze" 3 | version = "0.1.0" 4 | authors = ["Sean Hellum "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | structopt = "0.3.9" 9 | regex = "1" 10 | 11 | [build-dependencies] 12 | subprocess = "0.2.4" 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Gitpod Open Source 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dockerfreeze 2 | 3 | [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/gitpod-io/dockerfreeze) 4 | 5 | Freeze your development environment as a Dockerfile 6 | 7 | 8 | ***THIS IS A WIP*** 9 | 10 | Currently supported features 11 | 12 | * OS detection -- dockerfreeze will check your OS and choose a base image accordingly 13 | * Enviornment Variables -- dockerfreeze will iterate over your enviornment variable and replicate them in your Dockerfile 14 | 15 | ## Contributing 16 | 17 | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/JesterOrNot/dockerfreeze) 18 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | subprocess::Exec::shell("echo \"source ${PWD}/tools/dockerfreeze\" >> ~/.bashrc") 3 | .stdout(subprocess::Redirection::None) 4 | .join() 5 | .unwrap(); 6 | } 7 | -------------------------------------------------------------------------------- /gui/README.md: -------------------------------------------------------------------------------- 1 | # Docker Freeze Gui 2 | 3 | ## Requirements 4 | - Python 3.4+ 5 | 6 | ## License :scroll: 7 | This project is lisenced under MIT. Check license file for more info. 8 | -------------------------------------------------------------------------------- /gui/gui.py: -------------------------------------------------------------------------------- 1 | import PySimpleGUI as sg 2 | from os import system 3 | from os.path import exists 4 | from termcolor import cprint 5 | 6 | # Theme 7 | sg.theme('DarkAmber') 8 | 9 | 10 | def warn(error): 11 | cprint(f"Error: {error}", "red") 12 | sg.popup(f"Error: {error}", title="Attention!") 13 | 14 | 15 | def main(): 16 | layout = [ 17 | [sg.Text('Welcome To Dockerfreeze GUI')], 18 | [sg.T(" " * 7), sg.Text('Gitpod Ready', size=(12, 1)), sg.Checkbox("", default=False)], 19 | [sg.T(" " * 3), sg.Submit("BUILD"), sg.Cancel()] 20 | ] 21 | 22 | mainWindow = sg.Window('Dockerfreeze GUI', default_element_size=(40, 1)).Layout(layout) 23 | cprint("Main Window Running", "green") 24 | 25 | while True: # Event Loop 26 | button, values = mainWindow.Read() 27 | if button in ("Cancel", None): 28 | break 29 | if button == "BUILD": 30 | did_error = False 31 | if exists("Dockerfile"): 32 | warn("File already exists") 33 | continue 34 | if values[0]: 35 | if system("dockerfreeze -g &> /dev/null") != 0: 36 | did_error = True 37 | else: 38 | if system("dockerfreeze &> /dev/null") != 0: 39 | did_error = True 40 | if did_error: 41 | warn("File already exists") 42 | else: 43 | sg.popup("Dockerfile Built") 44 | did_error = False 45 | cprint("Closing Application...", "red") 46 | mainWindow.close() 47 | 48 | 49 | if __name__ == "__main__": 50 | main() 51 | -------------------------------------------------------------------------------- /gui/license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Uniminin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gui/requirements.txt: -------------------------------------------------------------------------------- 1 | PySimpleGUI==4.18.0 2 | termcolor==1.1.0 3 | -------------------------------------------------------------------------------- /src/detection.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::Read; 3 | 4 | pub fn get_distro() -> String { 5 | let mut content = String::new(); 6 | let mut os_release = File::open("/etc/os-release").unwrap(); 7 | let regex = regex::Regex::new(".*\nID=(.*)\n").unwrap(); 8 | os_release.read_to_string(&mut content).unwrap(); 9 | return regex 10 | .captures(&content) 11 | .unwrap() 12 | .get(1) 13 | .unwrap() 14 | .as_str() 15 | .to_owned(); 16 | } 17 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::Write; 3 | use structopt::StructOpt; 4 | 5 | #[derive(StructOpt)] 6 | pub struct Cli { 7 | /// Output file for Dockerfile 8 | #[structopt(short = "o", long = "output")] 9 | pub file: Option, 10 | /// Optimize Dockerfile for Gitpod 11 | #[structopt(short, long, parse(from_flag))] 12 | pub gitpod: bool, 13 | } 14 | 15 | pub fn match_dist(distro: &str, file: &mut File) -> usize { 16 | match distro { 17 | "ubuntu" => file.write(b"FROM ubuntu:latest\n").unwrap(), 18 | "alpine" => file.write(b"FROM alpine:latest\n").unwrap(), 19 | "debian" => file.write(b"FROM debian:latest\n").unwrap(), 20 | _ => { 21 | println!( 22 | "\x1b[33mUnknown Distro \"{}\" Re-routing to Ubuntu\x1b[0m", 23 | distro 24 | ); 25 | file.write("FROM ubuntu:latest\n".as_bytes()).unwrap() 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod detection; 2 | mod lib; 3 | mod write; 4 | 5 | use crate::lib::Cli; 6 | use crate::write::write_env_vars; 7 | use crate::write::write_linux_distro; 8 | use std::fs::OpenOptions; 9 | use std::process::exit; 10 | use structopt::StructOpt; 11 | 12 | fn main() { 13 | let args = Cli::from_args(); 14 | let mut file = match args.file { 15 | Some(n) => match OpenOptions::new().write(true).create_new(true).open(n) { 16 | Ok(n) => { 17 | println!("\x1b[1;32mFile Created!\x1b[m"); 18 | n 19 | } 20 | Err(_) => { 21 | println!("\x1b[1;31mError: File Already Exists!\x1b[m"); 22 | exit(1); 23 | } 24 | }, 25 | None => { 26 | match OpenOptions::new() 27 | .write(true) 28 | .create_new(true) 29 | .open("Dockerfile") 30 | { 31 | Ok(n) => { 32 | println!("\x1b[1;32mFile Created!\x1b[m"); 33 | n 34 | } 35 | Err(_) => { 36 | println!("\x1b[1;31mError: File Already Exists!\x1b[m"); 37 | exit(1); 38 | } 39 | } 40 | } 41 | }; 42 | write_linux_distro(&mut file); 43 | write_env_vars(&mut file); 44 | } 45 | -------------------------------------------------------------------------------- /src/write.rs: -------------------------------------------------------------------------------- 1 | use crate::detection::get_distro; 2 | use crate::lib::match_dist; 3 | use crate::lib::Cli; 4 | use std::env::vars; 5 | use std::fs::File; 6 | use std::io::Write; 7 | use structopt::StructOpt; 8 | 9 | pub fn write_linux_distro(file: &mut File) { 10 | let distro = get_distro(); 11 | let args = Cli::from_args(); 12 | match args.gitpod { 13 | true => file.write(b"FROM gitpod/workspace-full:latest\n").unwrap(), 14 | false => match_dist(&distro, file), 15 | }; 16 | } 17 | 18 | pub fn write_env_vars(file: &mut File) { 19 | let mut count = 0; 20 | let length = vars().count() - 1; 21 | for (key, value) in vars() { 22 | let value = value.replace("\"", "\\\""); 23 | if value.contains(" ") || value.contains("{") || value.contains("}") { 24 | if count == 0 { 25 | &file 26 | .write(format!("ENV {}=\"{}\" \\\n", key, value).as_bytes()) 27 | .unwrap(); 28 | } else if count != length { 29 | &file 30 | .write(format!(" {}=\"{}\" \\\n", key, value).as_bytes()) 31 | .unwrap(); 32 | } else { 33 | &file 34 | .write(format!(" {}=\"{}\"", key, value).as_bytes()) 35 | .unwrap(); 36 | } 37 | } else { 38 | if count == 0 { 39 | &file 40 | .write(format!("ENV {}={} \\\n", key, value).as_bytes()) 41 | .unwrap(); 42 | } else if count != length { 43 | &file 44 | .write(format!(" {}={} \\\n", key, value).as_bytes()) 45 | .unwrap(); 46 | } else { 47 | &file 48 | .write(format!(" {}={}", key, value).as_bytes()) 49 | .unwrap(); 50 | } 51 | } 52 | count += 1; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tools/dockerfreeze: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # shellcheck shell=bash 4 | # Affected by https://github.com/koalaman/shellcheck/issues/1771 for directives comments 5 | 6 | _dockerfreeze() { 7 | local cur prev opts 8 | # shellcheck disable=SC2034 # used by complete 9 | COMREPLY=() 10 | cur="${COMP_WORDS[COMP_CWORD]}" 11 | # shellcheck disable=SC2034 # used by complete 12 | prev="${COMP_WORDS[COMP_CWORD-1]}" 13 | opts="-g -h -v -o --version --help --gitpod --output" 14 | if [[ ${cur} == -* ]] ; then 15 | COMPREPLY=( "$(compgen -W "$opts" -- "$cur")" ) 16 | return 0 17 | elif [[ ${cur} == r* ]]; then 18 | COMPREPLY=( "$(compgen -W "$opts" "$cur")" ) 19 | return 0 20 | fi 21 | } 22 | complete -F _dockerfreeze dockerfreeze 23 | --------------------------------------------------------------------------------