Full Code of ubnt-intrepid/dot for AI

main 3aba0a6ffa89 cached
20 files
33.9 KB
9.6k tokens
73 symbols
1 requests
Download .txt
Repository: ubnt-intrepid/dot
Branch: main
Commit: 3aba0a6ffa89
Files: 20
Total size: 33.9 KB

Directory structure:
gitextract_ylvdtk3u/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── ci/
│   ├── before_deploy.ps1
│   ├── before_deploy.sh
│   ├── install.sh
│   └── script.sh
├── rust-toolchain.toml
├── scripts/
│   └── bootstrap.sh
├── src/
│   ├── app.rs
│   ├── dotfiles.rs
│   ├── entry.rs
│   ├── lib.rs
│   ├── main.rs
│   ├── util.rs
│   └── windows.rs
├── templates/
│   └── mappings-example.toml
└── tests/
    └── dotfiles/
        └── .mappings

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/build.yml
================================================
name: Build

on:
  push:
    branches:
      - main
    tags:
      - 'v*'
  pull_request:
    branches:
      - main

env:
  CARGO_TERM_VERBOSE: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Cache dependencies
      uses: actions/cache@v4
      with:
        path: |
          ~/.cargo/registry
          ~/.cargo/git
          target
        key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

    - name: Run test
      run: cargo test


================================================
FILE: .gitignore
================================================
target/
*.tar.gz
dot-*/
completions/


================================================
FILE: Cargo.toml
================================================
[package]
name = "dot"
version = "0.2.0-dev"
publish = false
description = "Alternative of dotfile management frameworks"
edition = "2018"

[dependencies]
ansi_term = "0.9"
clap = "3"
clap_complete = "3"
error-chain = "0.12.1"
regex = "1.11"
shellexpand = "1"
toml = "0.4"
url = "2.5"
dirs = "2.0.2"

[target.'cfg(windows)'.dependencies]
winapi = "0.2.8"
advapi32-sys = "0.2.0"
kernel32-sys = "0.2.2"
runas = "0.1.1"


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 Yusuke Sasaki

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# `dot`

![GitHub Actions](https://github.com/ubnt-intrepid/dot/workflows/Workflow/badge.svg)

`dot` is a command-line tool for managing dotfiles, written in Rust.

## Overview
`dot` provides a way to organize configuration files in your home directory.

## Installation
Precompiled binaries are on our [GitHub releases page](https://github.com/ubnt-intrepid/dot/releases/latest).
If you want to use the development version, try `cargo install` to build from source:

```shell-session
$ cargo install --git https://github.com/ubnt-intrepid/dot.git
```

## Example Usage
Clone your dotfiles repository from github and then create home directory symlinks:  
```sh
$ dot init ubnt-intrepid/dotfiles
```

Check if all of the links exist and are correct:
```sh
$ dot check
```

`<pattern>` determines the remote repository's URL of dotfiles.

Pattern types:

* `(http|https|ssh|git)://[username@]github.com[:port]/path-to-repo.git` – URL of dotfiles repository
* `git@github.com:path-to-repo.git` – SCP-like path
* `username/dotfiles` – GitHub user and repository
* `username` – GitHub user only (repository `dotfiles`, e.g.: `https://github.com/myuser/dotfiles`)

By default, the repository will be cloned locally to `$HOME/.dotfiles`. This can be overridden with `$DOT_DIR`.

For more information, run `dot help`.

## Configuration
`$DOT_DIR/.mappings` where the symlinks are defined in [TOML](https://github.com/toml-lang/toml). For example:

```toml
[general]
gitconfig   = "~/.gitconfig"
"vim/vimrc" = ["~/.vimrc", "~/.config/nvim/init.vim"]
#...

[windows]
vscode = "$APPDATA/Code/User"
powershell = "$HOME/Documents/WindowsPowerShell"
#...

[linux]
xinitrc = "~/.xinitrc"
```

Use `[general]` for symlinks on all platforms. `[windows]`, `[linux]`, `[macos]` for symlinks on specific platforms.

See [my dotfiles](https://github.com/ubnt-intrepid/dotfiles) for a real example.

## License
`dot` is distributed under the MIT license.
See [LICENSE](LICENSE) for details.

## Similar Projects
- [ssh0/dot](https://github.com/ssh0/dot)  
  written in shell script
- [rhysd/dotfiles](https://github.com/rhysd/dotfiles)  
  written in Golang


================================================
FILE: ci/before_deploy.ps1
================================================
# This script takes care of packaging the build artifacts that will go in the
# release zipfile

$SRC_DIR = $PWD.Path
$STAGE = [System.Guid]::NewGuid().ToString()

Set-Location $ENV:Temp
New-Item -Type Directory -Name $STAGE
Set-Location $STAGE

$ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip"

# TODO Update this to package the right artifacts
Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\dot.exe" '.\'

7z a "$ZIP" *

Push-AppveyorArtifact "$ZIP"

Remove-Item *.* -Force
Set-Location ..
Remove-Item $STAGE
Set-Location $SRC_DIR


================================================
FILE: ci/before_deploy.sh
================================================
#!/bin/bash

# This script takes care of building your crate and packaging it for release

set -ex

main() {
    local src=$(pwd) \
          stage=

    case $TRAVIS_OS_NAME in
        linux)
            stage=$(mktemp -d)
            ;;
        osx)
            stage=$(mktemp -d -t tmp)
            ;;
    esac

    test -f Cargo.lock || cargo generate-lockfile

    # TODO Update this to build the artifacts that matter to you
    cross rustc --bin dot --target $TARGET --release -- -C lto

    # TODO Update this to package the right artifacts
    cp target/$TARGET/release/dot $stage/

    cd $stage
    tar czf $src/$CRATE_NAME-$TRAVIS_TAG-$TARGET.tar.gz *
    cd $src

    rm -rf $stage
}

main


================================================
FILE: ci/install.sh
================================================
#!/bin/bash

# copied from trust

set -ex

main() {
    local target=
    if [ $TRAVIS_OS_NAME = linux ]; then
        target=x86_64-unknown-linux-musl
        sort=sort
    else
        target=x86_64-apple-darwin
        sort=gsort  # for `sort --sort-version`, from brew's coreutils.
    fi

    # This fetches latest stable release
    local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \
                       | cut -d/ -f3 \
                       | grep -E '^v[0.1.0-9.]+$' \
                       | $sort --version-sort \
                       | tail -n1)
    curl -LSfs https://japaric.github.io/trust/install.sh | \
        sh -s -- \
           --force \
           --git japaric/cross \
           --tag $tag \
           --target $target
}

main


================================================
FILE: ci/script.sh
================================================
#!/bin/bash

set -ex

# TODO This is the "test phase", tweak it as you see fit
main() {
    cross build --target $TARGET --release

    if [ ! -z $DISABLE_TESTS ]; then
        return
    fi

    cross test --target $TARGET --release
}

# we don't run the "test phase" when doing deploys
if [ -z $TRAVIS_TAG ]; then
    main
fi


================================================
FILE: rust-toolchain.toml
================================================
[toolchain]
channel = "stable"
profile = "minimal"
components = [ "rustfmt", "clippy" ]



================================================
FILE: scripts/bootstrap.sh
================================================
#!/bin/bash -e

# Usage:
# DOTURL=https://github.com/ubnt-intrepid/.dotfiles.git [PREFIX=$HOME/.local] ./bootstrap.sh

# Repository URL of your dotfiles.
DOT_URL=${DOT_URL:-"https://github.com/ubnt-intrepid/.dotfiles.git"}

#
DOT_DIR=${DOT_DIR:-"$HOME/.dotfiles"}

# installation directory of `dot`
PREFIX=${PREFIX:-"$HOME/.local"}


# --- export as environment variables
export DOT_DIR


# --- download `dot.rs` from GitHub Releases and install
case `uname -s | tr '[A-Z]' '[a-z]'` in
  *mingw* | *msys*)
    DOTRS_SUFFIX="`uname -m`-windows-msvc"
    ;;
  *darwin*)
    DOTRS_SUFFIX="`uname -m`-apple-darwin"
    ;;
  *linux*)
    DOTRS_SUFFIX="`uname -m`-unknown-linux-musl"
    ;;
  *android*)
    # TODO: support for other architectures
    DOTRS_SUFFIX="arm-linux-androideabi"
    ;;
  *)
    echo "[fatal] cannot recognize the platform."
    exit 1
esac

DOTRS_URL="`curl -s https://api.github.com/repos/ubnt-intrepid/dot.rs/releases | grep browser_download_url | cut -d '"' -f 4 | grep "$DOTRS_SUFFIX" | head -n 1`"
echo "$DOTRS_URL"

mkdir -p "${PREFIX}/bin"
curl -sL "${DOTRS_URL}" | tar xz -C "$PREFIX/bin/" --strip=1 './dot'

export PATH="$PREFIX/bin:$PATH"

# --- clone your dotfiles into home directory, and make links.
[[ -d "$DOT_DIR" ]] || git clone "$DOT_URL" "$DOT_DIR"
dot link --verbose


================================================
FILE: src/app.rs
================================================
use crate::dotfiles::Dotfiles;
use crate::errors::Result;
use crate::util;
use dirs;
use regex::Regex;
use std::borrow::Borrow;
use std::env;
use std::path::Path;
use url::Url;

#[cfg(windows)]
use crate::windows;

pub struct App {
    dotfiles: Dotfiles,
    dry_run: bool,
    verbose: bool,
}

impl App {
    pub fn new(dry_run: bool, verbose: bool) -> Result<App> {
        let dotdir = init_envs()?;
        let dotfiles = Dotfiles::new(Path::new(&dotdir).to_path_buf());
        Ok(App {
            dotfiles: dotfiles,
            dry_run: dry_run,
            verbose: verbose,
        })
    }

    pub fn command_clone(&self, query: &str) -> Result<i32> {
        let url = resolve_url(query)?;
        let dotdir = self.dotfiles.root_dir().to_string_lossy();
        util::wait_exec(
            "git",
            &["clone", url.as_str(), dotdir.borrow()],
            None,
            self.dry_run,
        )
        .map_err(Into::into)
    }

    pub fn command_root(&self) -> Result<i32> {
        println!("{}", self.dotfiles.root_dir().display());
        Ok(0)
    }

    pub fn command_check(&mut self) -> Result<i32> {
        self.dotfiles.read_entries();

        let mut num_unhealth = 0;
        for entry in self.dotfiles.entries() {
            if entry.check(self.verbose).unwrap() == false {
                num_unhealth += 1;
            }
        }
        Ok(num_unhealth)
    }

    pub fn command_link(&mut self) -> Result<i32> {
        self.dotfiles.read_entries();

        if !self.dry_run {
            check_symlink_privilege();
        }

        for entry in self.dotfiles.entries() {
            entry.mklink(self.dry_run, self.verbose).unwrap();
        }

        Ok(0)
    }

    pub fn command_clean(&mut self) -> Result<i32> {
        self.dotfiles.read_entries();

        for entry in self.dotfiles.entries() {
            entry.unlink(self.dry_run, self.verbose).unwrap();
        }

        Ok(0)
    }
}

#[cfg(windows)]
fn check_symlink_privilege() {
    use windows::ElevationType;

    match windows::get_elevation_type().unwrap() {
        ElevationType::Default => {
            match windows::enable_privilege("SeCreateSymbolicLinkPrivilege") {
                Ok(_) => (),
                Err(err) => panic!("failed to enable SeCreateSymbolicLinkPrivilege: {}", err),
            }
        }
        ElevationType::Limited => {
            panic!("should be elevate as an Administrator.");
        }
        ElevationType::Full => (),
    }
}

#[cfg(not(windows))]
#[inline]
pub fn check_symlink_privilege() {}

fn init_envs() -> Result<String> {
    if env::var("HOME").is_err() {
        env::set_var("HOME", dirs::home_dir().unwrap());
    }

    let dotdir = env::var("DOT_DIR")
        .or(util::expand_full("$HOME/.dotfiles"))
        .map_err(|_| "failed to determine dotdir".to_string())?;
    env::set_var("DOT_DIR", dotdir.as_str());
    env::set_var("dotdir", dotdir.as_str());

    Ok(dotdir)
}

fn resolve_url(s: &str) -> Result<Url> {
    let re_scheme = Regex::new(r"^([^:]+)://").unwrap();
    let re_scplike = Regex::new(r"^((?:[^@]+@)?)([^:]+):/?(.+)$").unwrap();

    if let Some(cap) = re_scheme.captures(s) {
        match cap.get(1).unwrap().as_str() {
            "http" | "https" | "ssh" | "git" | "file" => Url::parse(s).map_err(Into::into),
            scheme => Err(format!("'{}' is invalid scheme", scheme).into()),
        }
    } else if let Some(cap) = re_scplike.captures(s) {
        let username = cap
            .get(1)
            .and_then(|s| {
                if s.as_str() != "" {
                    Some(s.as_str())
                } else {
                    None
                }
            })
            .unwrap_or("git@");
        let host = cap.get(2).unwrap().as_str();
        let path = cap.get(3).unwrap().as_str();

        Url::parse(&format!("ssh://{}{}/{}.git", username, host, path)).map_err(Into::into)
    } else {
        let username = s
            .splitn(2, "/")
            .next()
            .ok_or("'username' is unknown".to_owned())?;
        let reponame = s.splitn(2, "/").skip(1).next().unwrap_or("dotfiles");
        Url::parse(&format!("https://github.com/{}/{}.git", username, reponame)).map_err(Into::into)
    }
}


================================================
FILE: src/dotfiles.rs
================================================
use crate::entry::Entry;
use crate::util;
use std::path::{Path, PathBuf};
use toml;

pub struct Dotfiles {
    _root_dir: PathBuf,
    _entries: Vec<Entry>,
}

impl Dotfiles {
    pub fn new(root_dir: PathBuf) -> Dotfiles {
        Dotfiles {
            _root_dir: root_dir,
            _entries: Vec::new(),
        }
    }

    pub fn read_entries(&mut self) {
        self._entries = read_entries(self._root_dir.as_path());
    }

    pub fn root_dir(&self) -> &Path {
        self._root_dir.as_path()
    }

    pub fn entries(&self) -> &[Entry] {
        self._entries.as_slice()
    }
}

fn read_entries(root_dir: &Path) -> Vec<Entry> {
    let ref entries = util::read_toml(root_dir.join(".mappings")).unwrap();

    let mut buf = Vec::new();
    read_entries_from_key(&mut buf, entries, root_dir, "general");
    read_entries_from_key(&mut buf, entries, root_dir, util::OS_NAME);

    buf
}

fn new_entry(root_dir: &Path, key: &str, val: &str) -> Entry {
    let src = util::expand_full(&format!("{}/{}", root_dir.display(), key)).unwrap();

    let mut dst = util::expand_full(val).unwrap();
    if Path::new(&dst).is_relative() {
        dst = util::expand_full(&format!("$HOME/{}", val)).unwrap();
    }

    Entry::new(&src, &dst)
}

fn read_entries_from_key(
    buf: &mut Vec<Entry>,
    entries: &toml::value::Table,
    root_dir: &Path,
    key: &str,
) {
    if let Some(entries_table) = entries.get(key).and_then(|value| value.as_table()) {
        for (ref key, ref val) in entries_table.iter() {
            if let Some(val) = val.as_str() {
                buf.push(new_entry(root_dir, key, val));
            }
            if let Some(val) = val.as_array() {
                for v in val {
                    if let Some(v) = v.as_str() {
                        buf.push(new_entry(root_dir, key, v));
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{read_entries_from_key, Dotfiles};
    use crate::util;
    use std::path::Path;

    #[test]
    fn smoke_test() {
        let root_dir = Path::new("tests/dotfiles").to_path_buf();
        let mut dotfiles = Dotfiles::new(root_dir);
        assert_eq!(Path::new("tests/dotfiles"), dotfiles.root_dir());
        dotfiles.read_entries();
    }

    #[test]
    fn do_nothing_if_given_key_is_not_exist() {
        let root_dir = Path::new("tests/dotfiles").to_path_buf();
        let entries = util::read_toml(root_dir.join(".mappings")).unwrap();

        let mut buf = Vec::new();
        read_entries_from_key(&mut buf, &entries, &root_dir, "hogehoge");
        assert_eq!(buf.len(), 0);
    }
}


================================================
FILE: src/entry.rs
================================================
use crate::util;
use ansi_term;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EntryStatus {
    Healthy,
    LinkNotCreated,
    NotSymLink,
    WrongLinkPath,
}

#[derive(Debug, Clone)]
pub struct Entry {
    src: PathBuf,
    dst: PathBuf,
}

impl Entry {
    pub fn new(src: &str, dst: &str) -> Entry {
        Entry {
            src: util::make_pathbuf(src),
            dst: util::make_pathbuf(dst),
        }
    }

    pub fn status(&self) -> Result<EntryStatus, io::Error> {
        let status = if !self.dst.exists() {
            EntryStatus::LinkNotCreated
        } else if !util::is_symlink(&self.dst)? {
            EntryStatus::NotSymLink
        } else if self.src != self.dst.read_link()? {
            EntryStatus::WrongLinkPath
        } else {
            EntryStatus::Healthy
        };

        Ok(status)
    }

    pub fn check(&self, verbose: bool) -> Result<bool, io::Error> {
        let status = self.status()?;
        if status != EntryStatus::Healthy {
            println!(
                "{} {} ({:?})",
                ansi_term::Style::new()
                    .bold()
                    .fg(ansi_term::Colour::Red)
                    .paint("✘"),
                self.dst.display(),
                status
            );
            return Ok(false);
        }
        if verbose {
            println!(
                "{} {}\n  => {}",
                ansi_term::Style::new()
                    .bold()
                    .fg(ansi_term::Colour::Green)
                    .paint("✓"),
                self.dst.display(),
                self.src.display()
            );
        }
        Ok(true)
    }

    pub fn mklink(&self, dry_run: bool, verbose: bool) -> Result<(), io::Error> {
        if !self.src.exists() || self.status()? == EntryStatus::Healthy {
            return Ok(()); // Do nothing.
        }

        if self.dst.exists() && !util::is_symlink(&self.dst)? {
            let origpath = orig_path(&self.dst);
            println!(
                "file {} has already existed. It will be renamed to {}",
                self.dst.display(),
                origpath.display()
            );
            fs::rename(&self.dst, origpath)?;
        }

        if verbose {
            println!("{}\n  => {}", self.dst.display(), self.src.display());
        }
        util::make_link(&self.src, &self.dst, dry_run)
    }

    pub fn unlink(&self, dry_run: bool, verbose: bool) -> Result<(), io::Error> {
        if !self.dst.exists() || !util::is_symlink(&self.dst)? {
            return Ok(()); // do nothing
        }

        if verbose {
            println!("unlink {}", self.dst.display());
        }
        util::remove_link(&self.dst, dry_run)?;

        let origpath = orig_path(&self.dst);
        if origpath.exists() {
            fs::rename(origpath, &self.dst)?;
        }

        Ok(())
    }
}

fn orig_path<P: AsRef<Path>>(path: P) -> PathBuf {
    let origpath = format!("{}.bk", path.as_ref().to_str().unwrap());
    Path::new(&origpath).to_path_buf()
}


================================================
FILE: src/lib.rs
================================================
extern crate ansi_term;
extern crate shellexpand;
extern crate toml;
#[macro_use]
extern crate error_chain;
extern crate regex;
extern crate url;

#[cfg(windows)]
extern crate advapi32;
#[cfg(windows)]
extern crate kernel32;
#[cfg(windows)]
extern crate winapi;

pub mod app;
mod dotfiles;
mod entry;
pub mod util;
#[cfg(windows)]
mod windows;

mod errors {
    error_chain! {
      foreign_links {
        Io(::std::io::Error);
        UrlParse(::url::ParseError);
      }
    }
}
pub use crate::errors::*;

pub use crate::app::App;


================================================
FILE: src/main.rs
================================================
extern crate clap;
extern crate dot;

use clap::{AppSettings, Arg, SubCommand};
use dot::App;

pub fn main() {
    match run() {
        Ok(retcode) => std::process::exit(retcode),
        Err(err) => panic!("unknown error: {}", err),
    }
}

pub fn run() -> dot::Result<i32> {
    let matches = cli().get_matches();
    let dry_run = matches.is_present("dry-run");
    let verbose = matches.is_present("verbose");

    let mut app = App::new(dry_run, verbose)?;

    match matches.subcommand() {
        Some(("check", _)) => app.command_check(),
        Some(("link", _)) => app.command_link(),
        Some(("clean", _)) => app.command_clean(),
        Some(("root", _)) => app.command_root(),

        Some(("clone", args)) => {
            let url = args.value_of("url").unwrap();
            app.command_clone(url)
        }

        Some(("init", args)) => {
            let url = args.value_of("url").unwrap();
            let ret = app.command_clone(url)?;
            if ret != 0 {
                return Ok(ret);
            }
            app.command_link()
        }

        Some(("completion", args)) => {
            let shell: clap_complete::Shell = args.value_of_t_or_exit("shell");
            clap_complete::generate(
                shell,
                &mut cli(),
                env!("CARGO_PKG_NAME"),
                &mut std::io::stdout(),
            );
            Ok(0)
        }

        Some(..) | None => unreachable!(),
    }
}

fn cli() -> clap::Command<'static> {
    clap::Command::new(env!("CARGO_PKG_NAME"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(
            Arg::with_name("verbose")
                .help("Use verbose output")
                .long("verbose")
                .short('v'),
        )
        .arg(
            Arg::with_name("dry-run")
                .help("do not actually perform I/O operations")
                .long("dry-run")
                .short('n'),
        )
        .subcommand(
            SubCommand::with_name("check")
                .about("Check the files are correctly linked to the right places"),
        )
        .subcommand(
            SubCommand::with_name("link")
                .about("Create all of the symbolic links into home directory"),
        )
        .subcommand(
            SubCommand::with_name("clean")
                .about("Remote all of registered links from home directory"),
        )
        .subcommand(
            SubCommand::with_name("root")
                .about("Show the location of dotfiles repository and exit"),
        )
        .subcommand(
            SubCommand::with_name("clone")
                .about("Clone dotfiles repository from remote")
                .arg(
                    Arg::with_name("url")
                        .help("URL of remote repository")
                        .required(true)
                        .takes_value(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("init")
                .about("Clone dotfiles repository from remote & make links")
                .arg(
                    Arg::with_name("url")
                        .help("URL of remote repository")
                        .required(true)
                        .takes_value(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("completion")
                .about("Generate completion scripts")
                .setting(AppSettings::ArgRequiredElseHelp)
                .arg(
                    Arg::with_name("shell")
                        .help("target shell")
                        .required(true)
                        .possible_values(&["bash", "fish", "zsh", "powershell"]),
                ),
        )
}


================================================
FILE: src/util.rs
================================================
use shellexpand::{self, LookupError};
use std::env;
use std::fs::{self, File};
use std::io::{self, Read};
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
use std::process::{Command, Stdio};
use toml;

#[allow(dead_code)]
pub fn wait_exec(
    cmd: &str,
    args: &[&str],
    curr_dir: Option<&Path>,
    dry_run: bool,
) -> Result<i32, io::Error> {
    if dry_run {
        println!("{} {:?} (@ {:?})", cmd, args, curr_dir);
        return Ok(0);
    }

    let mut command = Command::new(cmd);
    command
        .args(args)
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit());
    if let Some(curr_dir) = curr_dir {
        command.current_dir(curr_dir);
    }

    let mut child = command.spawn()?;
    child
        .wait()
        .and_then(|st| st.code().ok_or(io::Error::new(io::ErrorKind::Other, "")))
}

pub fn expand_full(s: &str) -> Result<String, LookupError<env::VarError>> {
    shellexpand::full(s).map(|s| s.into_owned())
}

#[cfg(windows)]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<(), io::Error> {
    use std::os::windows::fs;
    if src.as_ref().is_dir() {
        fs::symlink_dir(src, dst)
    } else {
        fs::symlink_file(src, dst)
    }
}

#[cfg(not(windows))]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<(), io::Error> {
    use std::os::unix::fs::symlink;
    symlink(src, dst)
}

pub fn make_link<P, Q>(src: P, dst: Q, dry_run: bool) -> Result<(), io::Error>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    if dry_run {
        println!(
            "make_link({}, {})",
            src.as_ref().display(),
            dst.as_ref().display()
        );
        Ok(())
    } else {
        fs::create_dir_all(dst.as_ref().parent().unwrap())?;
        symlink(src, dst)
    }
}

#[cfg(windows)]
fn unlink<P: AsRef<Path>>(dst: P) -> Result<(), io::Error> {
    if dst.as_ref().is_dir() {
        fs::remove_dir(dst)
    } else {
        fs::remove_file(dst)
    }
}

#[cfg(not(windows))]
fn unlink<P: AsRef<Path>>(dst: P) -> Result<(), io::Error> {
    fs::remove_file(dst)
}

pub fn remove_link<P: AsRef<Path>>(dst: P, dry_run: bool) -> Result<(), io::Error> {
    if dry_run {
        println!("fs::remove_file {}", dst.as_ref().display());
        Ok(())
    } else {
        unlink(dst)
    }
}

pub fn read_toml<P: AsRef<Path>>(path: P) -> Result<toml::value::Table, io::Error> {
    let mut file = File::open(path)?;

    let mut buf = Vec::new();
    file.read_to_end(&mut buf)?;

    let content = String::from_utf8_lossy(&buf[..]).into_owned();
    toml::de::from_str(&content).map_err(|_| {
        io::Error::new(
            io::ErrorKind::Other,
            "failed to parse configuration file as TOML",
        )
    })
}

#[cfg(target_os = "windows")]
pub static OS_NAME: &'static str = "windows";

#[cfg(target_os = "macos")]
pub static OS_NAME: &'static str = "darwin";

#[cfg(target_os = "linux")]
pub static OS_NAME: &'static str = "linux";

#[cfg(target_os = "android")]
pub static OS_NAME: &'static str = "linux";

#[cfg(target_os = "freebsd")]
pub static OS_NAME: &'static str = "freebsd";

#[cfg(target_os = "openbsd")]
pub static OS_NAME: &'static str = "openbsd";

// create an instance of PathBuf from string.
pub fn make_pathbuf(path: &str) -> PathBuf {
    let path = path.replace("/", &format!("{}", MAIN_SEPARATOR));
    Path::new(&path).to_path_buf()
}

pub fn is_symlink<P: AsRef<Path>>(path: P) -> Result<bool, io::Error> {
    let meta = path.as_ref().symlink_metadata()?;
    Ok(meta.file_type().is_symlink())
}


================================================
FILE: src/windows.rs
================================================
//

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(improper_ctypes)]

use advapi32;
use kernel32;
use std::ffi::CString;
use std::mem;
use std::os::raw::c_void;
use std::ptr::{null, null_mut};
use winapi::winerror::ERROR_SUCCESS;
use winapi::winnt;
use winapi::LUID;

type BYTE = u8;
type BOOL = i32;
type DWORD = u32;

#[repr(C)]
struct TOKEN_ELEVATION {
    TokenIsElevated: DWORD,
}

type TOKEN_ELEVATION_TYPE = u32;

#[repr(C)]
struct TOKEN_GROUPS {
    GroupCount: DWORD,
    Groups: [SID_AND_ATTRIBUTES; 0],
}

#[repr(C)]
struct SID_AND_ATTRIBUTES {
    Sid: PSID,
    Attributes: DWORD,
}

#[repr(C)]
struct SID_IDENTIFIER_AUTHORITY {
    Value: [BYTE; 6],
}

#[repr(C)]
#[allow(improper_ctypes)]
struct SID;

type PSID = *mut SID;
type PSID_IDENTIFIER_AUTHORITY = *mut SID_IDENTIFIER_AUTHORITY;

#[allow(dead_code)]
enum TOKEN_INFORMATION_CLASS {
    TokenUser = 1,
    TokenGroups,
    TokenPrivileges,
    TokenOwner,
    TokenPrimaryGroup,
    TokenDefaultDacl,
    TokenSource,
    TokenType,
    TokenImpersonationLevel,
    TokenStatistics,
    TokenRestrictedSids,
    TokenSessionId,
    TokenGroupsAndPrivileges,
    TokenSessionReference,
    TokenSandBoxInert,
    TokenAuditPolicy,
    TokenOrigin,
    TokenElevationType,
    TokenLinkedToken,
    TokenElevation,
    TokenHasRestrictions,
    TokenAccessInformation,
    TokenVirtualizationAllowed,
    TokenVirtualizationEnabled,
    TokenIntegrityLevel,
    TokenUIAccess,
    TokenMandatoryPolicy,
    TokenLogonSid,
    TokenIsAppContainer,
    TokenCapabilities,
    TokenAppContainerSid,
    TokenAppContainerNumber,
    TokenUserClaimAttributes,
    TokenDeviceClaimAttributes,
    TokenRestrictedUserClaimAttributes,
    TokenRestrictedDeviceClaimAttributes,
    TokenDeviceGroups,
    TokenRestrictedDeviceGroups,
    TokenSecurityAttributes,
    TokenIsRestricted,
    MaxTokenInfoClass,
}

extern "system" {
    fn GetTokenInformation(
        TokenHandle: winnt::HANDLE,
        TokenInformationClass: DWORD,
        TokenInformation: *mut c_void,
        TokenInformationLength: DWORD,
        ReturnLength: *mut DWORD,
    ) -> BOOL;

    fn IsUserAnAdmin() -> BOOL;

    fn AllocateAndInitializeSid(
        pIdentifierAuthority: PSID_IDENTIFIER_AUTHORITY,
        nSubAuthorityCount: BYTE,
        dwSubAuthority0: DWORD,
        dwSubAuthority1: DWORD,
        dwSubAuthority2: DWORD,
        dwSubAuthority3: DWORD,
        dwSubAuthority4: DWORD,
        dwSubAuthority5: DWORD,
        dwSubAuthority6: DWORD,
        dwSubAuthority7: DWORD,
        pSid: *mut PSID,
    ) -> BOOL;
    fn FreeSid(pSid: PSID) -> *mut c_void;

    fn CheckTokenMembership(
        TokenHandle: winnt::HANDLE,
        SidToCheck: PSID,
        IsMember: *mut BOOL,
    ) -> BOOL;
}

struct Handle(winnt::HANDLE);

impl Handle {
    fn new(h: winnt::HANDLE) -> Handle {
        Handle(h)
    }

    fn as_raw(&self) -> winnt::HANDLE {
        self.0
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { kernel32::CloseHandle(self.0) };
        self.0 = null_mut();
    }
}

struct Sid(PSID);

impl Sid {
    fn as_raw(&self) -> PSID {
        self.0
    }
}

impl Drop for Sid {
    fn drop(&mut self) {
        unsafe { FreeSid(self.0) };
        self.0 = null_mut();
    }
}

pub fn enable_privilege(name: &str) -> Result<(), &'static str> {
    // 1. retrieve the process token of current process.
    let token = open_process_token(winnt::TOKEN_ADJUST_PRIVILEGES | winnt::TOKEN_QUERY)?;

    // 2. retrieve a LUID for given priviledge
    let luid = lookup_privilege_value(name)?;

    let len = mem::size_of::<winnt::TOKEN_PRIVILEGES>()
        + 1 * mem::size_of::<winnt::LUID_AND_ATTRIBUTES>();
    let token_privileges = vec![0u8; len];
    unsafe {
        let mut p = token_privileges.as_ptr() as *mut winnt::TOKEN_PRIVILEGES;
        let mut la = (*p).Privileges.as_ptr() as *mut winnt::LUID_AND_ATTRIBUTES;
        (*p).PrivilegeCount = 1;
        (*la).Luid = luid;
        (*la).Attributes = winnt::SE_PRIVILEGE_ENABLED;
    }

    unsafe {
        advapi32::AdjustTokenPrivileges(
            token.as_raw(),
            0,
            token_privileges.as_ptr() as *mut winnt::TOKEN_PRIVILEGES,
            0,
            null_mut(),
            null_mut(),
        );
    }

    match unsafe { kernel32::GetLastError() } {
        ERROR_SUCCESS => Ok(()),
        _ => Err("failed to adjust token privilege"),
    }
}

pub fn is_elevated() -> Result<bool, &'static str> {
    let token = open_process_token(winnt::TOKEN_QUERY)?;

    let mut elevation = TOKEN_ELEVATION { TokenIsElevated: 0 };
    let mut cb_size: u32 = mem::size_of_val(&elevation) as u32;
    let ret = unsafe {
        GetTokenInformation(
            token.as_raw(),
            mem::transmute::<_, u8>(TOKEN_INFORMATION_CLASS::TokenElevation) as u32,
            mem::transmute(&mut elevation),
            mem::size_of_val(&elevation) as u32,
            &mut cb_size,
        )
    };
    if ret == 0 {
        return Err("failed to get token information");
    }

    Ok(elevation.TokenIsElevated != 0)
}

#[derive(Debug, PartialEq)]
pub enum ElevationType {
    Default = 1,
    Full,
    Limited,
}

pub fn get_elevation_type() -> Result<ElevationType, &'static str> {
    let token = open_process_token(winnt::TOKEN_QUERY)?;

    let mut elev_type = 0;
    let mut cb_size = mem::size_of_val(&elev_type) as u32;
    let ret = unsafe {
        GetTokenInformation(
            token.as_raw(),
            mem::transmute::<_, u8>(TOKEN_INFORMATION_CLASS::TokenElevationType) as u32,
            mem::transmute(&mut elev_type),
            mem::size_of_val(&elev_type) as u32,
            &mut cb_size,
        )
    };
    if ret == 0 {
        return Err("failed to get token information");
    }

    match elev_type {
        1 => Ok(ElevationType::Default), // default (standard user/ administrator without UAC)
        2 => Ok(ElevationType::Full),    // full access (administrator, not elevated)
        3 => Ok(ElevationType::Limited), // limited access (administrator, not elevated)
        _ => Err("unknown elevation type"),
    }
}

fn open_process_token(token_type: u32) -> Result<Handle, &'static str> {
    let mut h_token = null_mut();
    let ret = unsafe {
        advapi32::OpenProcessToken(kernel32::GetCurrentProcess(), token_type, &mut h_token)
    };
    match ret {
        0 => Err("failed to get process token"),
        _ => Ok(Handle::new(h_token)),
    }
}

fn lookup_privilege_value(name: &str) -> Result<LUID, &'static str> {
    let mut luid = LUID {
        LowPart: 0,
        HighPart: 0,
    };
    let ret = unsafe {
        let name = CString::new(name).unwrap();
        advapi32::LookupPrivilegeValueA(null(), name.as_ptr(), &mut luid)
    };
    match ret {
        0 => Err("failed to get the privilege value"),
        _ => Ok(luid),
    }
}


================================================
FILE: templates/mappings-example.toml
================================================
# vim: set ft=toml ts=2 sw=2 et :

[general]
"tmux.conf"     = "~/.tmux.conf"
gitconfig       = "~/.gitconfig"
tigrc           = "~/.tigrc"
zsh             = "~/.config/zsh"
"zsh/zshenv"    = "~/.zshenv"
"zsh/zshrc"     = "~/.zshrc"
vim             = "~/.config/vim"
"vim/vimrc"     = "~/.vimrc"
"vim/gvimrc"    = "~/.gvimrc"

[windows]
atom                   = "~/.config/atom"
mintty                 = "~/.config/mintty"
"vscode/settings.json" = "$APPDATA/Code/User/settings.json"
"vscode/locale.json"   = "$APPDATA/Code/User/locale.json"
powershell             = "~/Documents/WindowsPowerShell"
consolez               = "$APPDATA/Console"
"ConEmu.xml"           = "$APPDATA/ConEmu.xml"

[linux]
neovim  = "~/.config/nvim"
xinitrc = "~/.xinitrc"
termux  = "~/.termux"
"virtualenvwrapper/postactivate" = "~/.virtualenvs/postactivate"
"virtualenvwrapper/postdeactivate" = "~/.virtualenvs/postdeactivate"


================================================
FILE: tests/dotfiles/.mappings
================================================
# vim: set ft=toml ts=2 sw=2 et :

[general]
"tmux.conf"     = "~/.tmux.conf"
gitconfig       = ["~/.gitconfig", "~/.config/git/config"]
tigrc           = "~/.tigrc"
zsh             = "~/.config/zsh"
"zsh/zshenv"    = "~/.zshenv"
"zsh/zshrc"     = "~/.zshrc"
vim             = ["~/.vim", "~/.config/nvim"]
"vim/vimrc"     = "~/.vimrc"
"vim/gvimrc"    = "~/.gvimrc"

[windows]
atom                   = "~/.config/atom"
mintty                 = "~/.config/mintty"
"vscode/settings.json" = "$APPDATA/Code/User/settings.json"
"vscode/locale.json"   = "$APPDATA/Code/User/locale.json"
powershell             = "~/Documents/WindowsPowerShell"
consolez               = "$APPDATA/Console"
"ConEmu.xml"           = "$APPDATA/ConEmu.xml"

[linux]
neovim  = "~/.config/nvim"
xinitrc = "~/.xinitrc"
termux  = "~/.termux"
"virtualenvwrapper/postactivate" = "~/.virtualenvs/postactivate"
"virtualenvwrapper/postdeactivate" = "~/.virtualenvs/postdeactivate"
Download .txt
gitextract_ylvdtk3u/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── ci/
│   ├── before_deploy.ps1
│   ├── before_deploy.sh
│   ├── install.sh
│   └── script.sh
├── rust-toolchain.toml
├── scripts/
│   └── bootstrap.sh
├── src/
│   ├── app.rs
│   ├── dotfiles.rs
│   ├── entry.rs
│   ├── lib.rs
│   ├── main.rs
│   ├── util.rs
│   └── windows.rs
├── templates/
│   └── mappings-example.toml
└── tests/
    └── dotfiles/
        └── .mappings
Download .txt
SYMBOL INDEX (73 symbols across 6 files)

FILE: src/app.rs
  type App (line 14) | pub struct App {
    method new (line 21) | pub fn new(dry_run: bool, verbose: bool) -> Result<App> {
    method command_clone (line 31) | pub fn command_clone(&self, query: &str) -> Result<i32> {
    method command_root (line 43) | pub fn command_root(&self) -> Result<i32> {
    method command_check (line 48) | pub fn command_check(&mut self) -> Result<i32> {
    method command_link (line 60) | pub fn command_link(&mut self) -> Result<i32> {
    method command_clean (line 74) | pub fn command_clean(&mut self) -> Result<i32> {
  function check_symlink_privilege (line 86) | fn check_symlink_privilege() {
  function check_symlink_privilege (line 105) | pub fn check_symlink_privilege() {}
  function init_envs (line 107) | fn init_envs() -> Result<String> {
  function resolve_url (line 121) | fn resolve_url(s: &str) -> Result<Url> {

FILE: src/dotfiles.rs
  type Dotfiles (line 6) | pub struct Dotfiles {
    method new (line 12) | pub fn new(root_dir: PathBuf) -> Dotfiles {
    method read_entries (line 19) | pub fn read_entries(&mut self) {
    method root_dir (line 23) | pub fn root_dir(&self) -> &Path {
    method entries (line 27) | pub fn entries(&self) -> &[Entry] {
  function read_entries (line 32) | fn read_entries(root_dir: &Path) -> Vec<Entry> {
  function new_entry (line 42) | fn new_entry(root_dir: &Path, key: &str, val: &str) -> Entry {
  function read_entries_from_key (line 53) | fn read_entries_from_key(
  function smoke_test (line 82) | fn smoke_test() {
  function do_nothing_if_given_key_is_not_exist (line 90) | fn do_nothing_if_given_key_is_not_exist() {

FILE: src/entry.rs
  type EntryStatus (line 8) | pub enum EntryStatus {
  type Entry (line 16) | pub struct Entry {
    method new (line 22) | pub fn new(src: &str, dst: &str) -> Entry {
    method status (line 29) | pub fn status(&self) -> Result<EntryStatus, io::Error> {
    method check (line 43) | pub fn check(&self, verbose: bool) -> Result<bool, io::Error> {
    method mklink (line 71) | pub fn mklink(&self, dry_run: bool, verbose: bool) -> Result<(), io::E...
    method unlink (line 92) | pub fn unlink(&self, dry_run: bool, verbose: bool) -> Result<(), io::E...
  function orig_path (line 111) | fn orig_path<P: AsRef<Path>>(path: P) -> PathBuf {

FILE: src/main.rs
  function main (line 7) | pub fn main() {
  function run (line 14) | pub fn run() -> dot::Result<i32> {
  function cli (line 56) | fn cli() -> clap::Command<'static> {

FILE: src/util.rs
  function wait_exec (line 10) | pub fn wait_exec(
  function expand_full (line 37) | pub fn expand_full(s: &str) -> Result<String, LookupError<env::VarError>> {
  function symlink (line 42) | fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<(),...
  function symlink (line 52) | fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<(),...
  function make_link (line 57) | pub fn make_link<P, Q>(src: P, dst: Q, dry_run: bool) -> Result<(), io::...
  function unlink (line 76) | fn unlink<P: AsRef<Path>>(dst: P) -> Result<(), io::Error> {
  function unlink (line 85) | fn unlink<P: AsRef<Path>>(dst: P) -> Result<(), io::Error> {
  function remove_link (line 89) | pub fn remove_link<P: AsRef<Path>>(dst: P, dry_run: bool) -> Result<(), ...
  function read_toml (line 98) | pub fn read_toml<P: AsRef<Path>>(path: P) -> Result<toml::value::Table, ...
  function make_pathbuf (line 132) | pub fn make_pathbuf(path: &str) -> PathBuf {
  function is_symlink (line 137) | pub fn is_symlink<P: AsRef<Path>>(path: P) -> Result<bool, io::Error> {

FILE: src/windows.rs
  type BYTE (line 18) | type BYTE = u8;
  type BOOL (line 19) | type BOOL = i32;
  type DWORD (line 20) | type DWORD = u32;
  type TOKEN_ELEVATION (line 23) | struct TOKEN_ELEVATION {
  type TOKEN_ELEVATION_TYPE (line 27) | type TOKEN_ELEVATION_TYPE = u32;
  type TOKEN_GROUPS (line 30) | struct TOKEN_GROUPS {
  type SID_AND_ATTRIBUTES (line 36) | struct SID_AND_ATTRIBUTES {
  type SID_IDENTIFIER_AUTHORITY (line 42) | struct SID_IDENTIFIER_AUTHORITY {
  type SID (line 48) | struct SID;
  type PSID (line 50) | type PSID = *mut SID;
  type PSID_IDENTIFIER_AUTHORITY (line 51) | type PSID_IDENTIFIER_AUTHORITY = *mut SID_IDENTIFIER_AUTHORITY;
  type TOKEN_INFORMATION_CLASS (line 54) | enum TOKEN_INFORMATION_CLASS {
  function GetTokenInformation (line 99) | fn GetTokenInformation(
  function IsUserAnAdmin (line 107) | fn IsUserAnAdmin() -> BOOL;
  function AllocateAndInitializeSid (line 109) | fn AllocateAndInitializeSid(
  function FreeSid (line 122) | fn FreeSid(pSid: PSID) -> *mut c_void;
  function CheckTokenMembership (line 124) | fn CheckTokenMembership(
  type Handle (line 131) | struct Handle(winnt::HANDLE);
    method new (line 134) | fn new(h: winnt::HANDLE) -> Handle {
    method as_raw (line 138) | fn as_raw(&self) -> winnt::HANDLE {
  method drop (line 144) | fn drop(&mut self) {
  type Sid (line 150) | struct Sid(PSID);
    method as_raw (line 153) | fn as_raw(&self) -> PSID {
  method drop (line 159) | fn drop(&mut self) {
  function enable_privilege (line 165) | pub fn enable_privilege(name: &str) -> Result<(), &'static str> {
  function is_elevated (line 200) | pub fn is_elevated() -> Result<bool, &'static str> {
  type ElevationType (line 222) | pub enum ElevationType {
  function get_elevation_type (line 228) | pub fn get_elevation_type() -> Result<ElevationType, &'static str> {
  function open_process_token (line 254) | fn open_process_token(token_type: u32) -> Result<Handle, &'static str> {
  function lookup_privilege_value (line 265) | fn lookup_privilege_value(name: &str) -> Result<LUID, &'static str> {
Condensed preview — 20 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (37K chars).
[
  {
    "path": ".github/workflows/build.yml",
    "chars": 508,
    "preview": "name: Build\n\non:\n  push:\n    branches:\n      - main\n    tags:\n      - 'v*'\n  pull_request:\n    branches:\n      - main\n\ne"
  },
  {
    "path": ".gitignore",
    "chars": 37,
    "preview": "target/\n*.tar.gz\ndot-*/\ncompletions/\n"
  },
  {
    "path": "Cargo.toml",
    "chars": 417,
    "preview": "[package]\nname = \"dot\"\nversion = \"0.2.0-dev\"\npublish = false\ndescription = \"Alternative of dotfile management frameworks"
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2016 Yusuke Sasaki\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 2137,
    "preview": "# `dot`\n\n![GitHub Actions](https://github.com/ubnt-intrepid/dot/workflows/Workflow/badge.svg)\n\n`dot` is a command-line t"
  },
  {
    "path": "ci/before_deploy.ps1",
    "chars": 574,
    "preview": "# This script takes care of packaging the build artifacts that will go in the\n# release zipfile\n\n$SRC_DIR = $PWD.Path\n$S"
  },
  {
    "path": "ci/before_deploy.sh",
    "chars": 703,
    "preview": "#!/bin/bash\n\n# This script takes care of building your crate and packaging it for release\n\nset -ex\n\nmain() {\n    local s"
  },
  {
    "path": "ci/install.sh",
    "chars": 795,
    "preview": "#!/bin/bash\n\n# copied from trust\n\nset -ex\n\nmain() {\n    local target=\n    if [ $TRAVIS_OS_NAME = linux ]; then\n        t"
  },
  {
    "path": "ci/script.sh",
    "chars": 328,
    "preview": "#!/bin/bash\n\nset -ex\n\n# TODO This is the \"test phase\", tweak it as you see fit\nmain() {\n    cross build --target $TARGET"
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 89,
    "preview": "[toolchain]\nchannel = \"stable\"\nprofile = \"minimal\"\ncomponents = [ \"rustfmt\", \"clippy\" ]\n\n"
  },
  {
    "path": "scripts/bootstrap.sh",
    "chars": 1308,
    "preview": "#!/bin/bash -e\n\n# Usage:\n# DOTURL=https://github.com/ubnt-intrepid/.dotfiles.git [PREFIX=$HOME/.local] ./bootstrap.sh\n\n#"
  },
  {
    "path": "src/app.rs",
    "chars": 4256,
    "preview": "use crate::dotfiles::Dotfiles;\nuse crate::errors::Result;\nuse crate::util;\nuse dirs;\nuse regex::Regex;\nuse std::borrow::"
  },
  {
    "path": "src/dotfiles.rs",
    "chars": 2636,
    "preview": "use crate::entry::Entry;\nuse crate::util;\nuse std::path::{Path, PathBuf};\nuse toml;\n\npub struct Dotfiles {\n    _root_dir"
  },
  {
    "path": "src/entry.rs",
    "chars": 3100,
    "preview": "use crate::util;\nuse ansi_term;\nuse std::fs;\nuse std::io;\nuse std::path::{Path, PathBuf};\n\n#[derive(Debug, Clone, Copy, "
  },
  {
    "path": "src/lib.rs",
    "chars": 534,
    "preview": "extern crate ansi_term;\nextern crate shellexpand;\nextern crate toml;\n#[macro_use]\nextern crate error_chain;\nextern crate"
  },
  {
    "path": "src/main.rs",
    "chars": 3894,
    "preview": "extern crate clap;\nextern crate dot;\n\nuse clap::{AppSettings, Arg, SubCommand};\nuse dot::App;\n\npub fn main() {\n    match"
  },
  {
    "path": "src/util.rs",
    "chars": 3583,
    "preview": "use shellexpand::{self, LookupError};\nuse std::env;\nuse std::fs::{self, File};\nuse std::io::{self, Read};\nuse std::path:"
  },
  {
    "path": "src/windows.rs",
    "chars": 6910,
    "preview": "//\n\n#![allow(non_camel_case_types)]\n#![allow(non_snake_case)]\n#![allow(dead_code)]\n#![allow(improper_ctypes)]\n\nuse advap"
  },
  {
    "path": "templates/mappings-example.toml",
    "chars": 904,
    "preview": "# vim: set ft=toml ts=2 sw=2 et :\n\n[general]\n\"tmux.conf\"     = \"~/.tmux.conf\"\ngitconfig       = \"~/.gitconfig\"\ntigrc    "
  },
  {
    "path": "tests/dotfiles/.mappings",
    "chars": 943,
    "preview": "# vim: set ft=toml ts=2 sw=2 et :\n\n[general]\n\"tmux.conf\"     = \"~/.tmux.conf\"\ngitconfig       = [\"~/.gitconfig\", \"~/.con"
  }
]

About this extraction

This page contains the full source code of the ubnt-intrepid/dot GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 20 files (33.9 KB), approximately 9.6k tokens, and a symbol index with 73 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!