{"id":35603627,"url":"https://github.com/asherikov/wshandler","last_synced_at":"2026-01-29T22:05:15.213Z","repository":{"id":186060892,"uuid":"622349269","full_name":"asherikov/wshandler","owner":"asherikov","description":"Workspace utility (an alternative to wstool and vcstool)","archived":false,"fork":false,"pushed_at":"2026-01-14T22:53:31.000Z","size":116,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-15T04:44:38.110Z","etag":null,"topics":["catkin-workspace","gitman","ros-workspace","vcs2l","vcstool","vcstools","version-control","wstool"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asherikov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-04-01T21:02:31.000Z","updated_at":"2026-01-14T22:53:34.000Z","dependencies_parsed_at":"2024-05-10T15:27:29.381Z","dependency_job_id":"f31b56b8-a579-4186-af7f-52c567fd8495","html_url":"https://github.com/asherikov/wshandler","commit_stats":null,"previous_names":["asherikov/wshandler"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/asherikov/wshandler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asherikov%2Fwshandler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asherikov%2Fwshandler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asherikov%2Fwshandler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asherikov%2Fwshandler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asherikov","download_url":"https://codeload.github.com/asherikov/wshandler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asherikov%2Fwshandler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28886882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T21:06:44.224Z","status":"ssl_error","status_checked_at":"2026-01-29T21:06:42.160Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["catkin-workspace","gitman","ros-workspace","vcs2l","vcstool","vcstools","version-control","wstool"],"created_at":"2026-01-05T02:06:12.520Z","updated_at":"2026-01-29T22:05:15.208Z","avatar_url":"https://github.com/asherikov.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"Introduction\n============\n\n`wshandler` is a workspace management utility similar to\n\u003chttps://github.com/dirk-thomas/vcstool\u003e (now\n\u003chttps://github.com/ros-infrastructure/vcs2l\u003e),\n\u003chttps://github.com/ErickKramer/ripvcs/\u003e, and discontinued\n\u003chttps://github.com/vcstools/wstool\u003e. It is also conceptually similar to\n\u003chttps://github.com/jacebrowning/gitman\u003e, which comes from a different\n(non-ROS) background.\n\nA workspace is a directory containing a set of packages (typically git\nrepositories), see\n\u003chttps://docs.ros.org/en/foxy/Tutorials/Beginner-Client-Libraries/Creating-A-Workspace/Creating-A-Workspace.html\u003e\nor \u003chttp://wiki.ros.org/catkin/workspaces\u003e for more information.\n\nKey features:\n- `wshandler` mimics `wstool`'s 'stateful' workflow dropped in `vcstool`, i.e.,\n  it is easy to keep track of your local changes with respect to the upstream;\n- `wshandler` is implemented in `bash` and relies on either `gojq`\n  \u003chttps://github.com/itchyny/gojq\u003e or `yq` \u003chttps://github.com/mikefarah/yq\u003e\n  for yaml processing;\n- currently supported package sources: `git`;\n- supported repository list formats: `repos` (default) and `rosinstall`\n  (\u003chttps://docs.ros.org/en/independent/api/rosinstall/html/rosinstall_file_format.html\u003e);\n- custom repository list extensions:\n    - repository entries can be tagged for selective updates and status\n      information, e.g., `wshandler: {tags: [mytag]}`, see `./tests/tags/` for\n      examples;\n    - experimental sparse checkouts for entries that contain `wshandler:\n      {sparse: [\u003cpath\u003e]}`, see `./tests/sparse` for examples.\n\n\nInstallation\n============\n\n`wshandler` is a bash script that can be placed anywhere, e.g., your\n`${HOME}/bin`. It requires `bash`, `git` and either `gojq` (default) or `yq` to\nwork. `gojq` is available via binary packages on many modern systems, but has\ncertain limitations, e.g., it always sorts entries and does not preserve\ncomments. `yq` is not available via debian packages on Ubuntu, but can be\ninstalled using `snap`. You can also find an AppImage bundle including\n`wshandler` and `yq` at \u003chttps://github.com/asherikov/wshandler/releases\u003e\n(`git` and `bash` must be present on the host system).\n\n\nUsage\n=====\n\n```\nUsage (default values are shown in curly braces):\n  wshandler [\u003cCOMMON_ARGS\u003e] [\u003cCOMMAND_ARGS\u003e] \u003cCOMMAND\u003e \u003cCOMMAND_ARGS\u003e\n\nNotation:\n  \u003cREQUIRED ARGUMENT\u003e\n  {DEFAULT VALUE}\n  [OPTIONAL ARGUMENT]\n  (VALID OPTIONS IN A LIST)\n\nCommon arguments:\n  -y|--yaml_tool auto|gojq|yq    {auto}               # Use gojq or yq, auto prefers gojq\n  -Y|--yaml_binary \u003cBINARY_PATH\u003e {yq|gojq}            # Override yaml tool (yq/gojq) path\n  -r|--root \u003cWORKSPACE_ROOT\u003e     {./}                 # Parent of --list if it is a path\n  -c|--cache \u003cCACHE_DIR\u003e         {\u003cWORKSPACE_ROOT\u003e}   # Temporary files created here\n  -t|--type rosinstall|repos     {repos}              # Repository list format\n  -i|--indent 1|2|3...           {4}                  # Default indentation in yaml repository list\n  -k|--keep-going                {false}              # Do not stop on errors\n  -l|--list \u003cFILENAME\u003e           {.rosinstall|.repos} # Default depends on --type,\n                                                      #can be specified multiple times,\n                                                      #mutually exclusive with -L\n  -L|--list-discover                                  # Automatically discover lists in the root,\n                                                      #recursively searches for *.\u003ctype\u003e files,\n                                                      #mutually exclusive with -l,\n                                                      #should be set after -r and -t.\n  -T|--tag \u003cTAG\u003e                 {}                   # Filter repositories by tags\n                                                      #can be specified multiple times\n  -q|--quiet                                          # Suppress most of the output\n\nRepository list commands:\n  Information:\n    [-u|--unsorted] status    # show workspace status\n    is_source_space           # check if a directory is a workspace\n\n  Initialization:\n    Common arguments:\n      [-p|--policy \u003cPOLICY1[,POLICY2]\u003e ({default}|shallow|nolfs)]\n        default   # plain clone\n        shallow   # shallow clone\n        nolfs     # disable git LFS\n    clone git \u003cLIST_REPOSITORY\u003e [\u003cBRANCH\u003e]    # clone workspace from a given repository\n    init [git \u003cPACKAGE_REPOSITORY\u003e ...]       # initialize new workspace\n\n  Modification:\n    [-p|--policy {ask}|add|show|clean] scrape \u003cDIRECTORY {\u003cWORKSPACE_ROOT\u003e}\u003e  # process unmanaged repositories\n      ask         # interactive mode\n      add         # automaticaly add repositories\n      show        # show unmanaged repositories\n      clean       # remove unmanaged repositories\n    add git \u003cPACKAGE_NAME\u003e \u003cPACKAGE_URL\u003e \u003cPACKAGE_VERSION\u003e    # add a repository\n    set_version_by_url \u003cPACKAGE_URL\u003e \u003cPACKAGE_VERSION\u003e        # set repository version\n    set_version_by_name \u003cPACKAGE_NAME\u003e \u003cPACKAGE_VERSION\u003e      # set repository version\n    set_version_to_hash                                       # set all repository versions to hash\n    pin                                                       # alias for set_version_to_hash\n    [-p|--policy \u003cPOLICY1[,POLICY2]\u003e ({active})] set_version_to_branch \u003cBRANCH_NAME\u003e  # change to the given branch\n      active      # switch if the given branch is checked out\n    remove \u003cPACKAGE_NAME\u003e ...                                 # remove repository from a list\n    remove_by_url \u003cPACKAGE_URL\u003e [\u003cPACKAGE_URL\u003e]               # remove repository from a list\n    [-p|--policy {keep}|replace] merge \u003cLIST_FILENAME\u003e        # merge repository list\n      keep        # keep original entries when there is a collision\n      replace     # replace entries when there is a collision\n\nRepository commands:\n  Selective commands (\u003cPACKAGE_NAME\u003e may be a pattern):\n    Common arguments:\n      [-j|--jobs \u003cNUM_THREADS\u003e {1}]       # use multiple jobs if possible\n      [-U|--unmanaged]                    # work on unmanaged repository directories: directory names must\n                                          #be given instead of package names, at least one is required,\n                                          #ignores --jobs\n    clean [\u003cPACKAGE_NAME\u003e ...]            # remove repository\n    prune [\u003cPACKAGE_NAME\u003e ...]            # git prune\n    push [\u003cPACKAGE_NAME\u003e ...]             # git push\n    unshallow [\u003cPACKAGE_NAME\u003e ...]        # git unshallow\n    feature_branches [\u003cPACKAGE_NAME\u003e ...] # list git feature branches\n    [-p|--policy \u003cPOLICY1[,POLICY2]\u003e ({default}|shallow|nolfs|rebase)] update [\u003cPACKAGE_NAME\u003e ...] # git pull\n      default      # plain clone\n      shallow      # shallow clone\n      nolfs        # disable git LFS\n      rebase       # do git pull with rebase\n      unmodified   # only unmodified repos\n      nosubmodules # do not checkout submodules\n\n  Generic commands:\n    [-j|--jobs \u003cNUM_THREADS\u003e {1}] foreach git '\u003cCOMMAND\u003e'  # execute command in each repository\n\n  Branching commands:\n    branch show ['\u003cGREP_PATTERN\u003e']                    # show matching branches\n    branch new \u003cBRANCH_NAME\u003e                          # create a new branch in modified repositories\n    branch allnew \u003cBRANCH_NAME\u003e                       # create a new branch in all repositories\n    branch delete \u003cBRANCH_NAME\u003e                       # delete branch from all repositories\n    branch merge \u003cBRANCH_NAME\u003e \u003cTARGET_BRANCH {main}\u003e # merge brach\n    commit '\u003cMESSAGE\u003e'                                # commit to modified repositories\n\nwshandler installation commands:\n  install_test_deps                                                           # install test dependeincies\n  [-p|--policy {skip_yaml_tool}|snap|download|apt] install \u003cBIN_PATH {~/bin}\u003e # install wshandler\n      skip_yaml_tool  # do not install yaml tool\n      snap            # install yaml tool (jq) using snap\n      download        # download yaml tool (jq)\n      apt             # install yaml tool (gojq) using apt\n  upgrade \u003cBIN_PATH {~/bin}\u003e              # upgrade wshandler\n  upgrade_appimage \u003cBIN_PATH {~/bin}\u003e     # upgrade wshandler AppImage\n```\n\nExamples\n========\n\n- `wshandler status`\n```\n\u003e\u003e\u003e wshandler status: git sources ---\nFlags: H - version hash mismatch, M - uncommited changes\nname              version  actual version              HM repository\n----              -------  --------------              -- ----------\nariles            pkg_ws_2 tags/ws-2.3.1-0-ge2748ad4      https://github.com/asherikov/ariles.git\nintrometry        main     tags/0.1.0-0-ga033cd5-dirty  M https://github.com/asherikov/intrometry.git\nthread_supervisor master   tags/1.1.0-0-gbbf8a09          https://github.com/asherikov/thread_supervisor.git\n\n\u003c\u003c\u003c wshandler status: git sources ---\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasherikov%2Fwshandler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasherikov%2Fwshandler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasherikov%2Fwshandler/lists"}