Git Product home page Git Product logo

bunches's Introduction

internal JetBrains project

Bunches Tool Set

Set of tools for storing similar git-branches in a single branch by moving files that have changes to bunch-files, files with additional special extension.

plugin.xml
plugin.xml.172 <-- Bunch file for Idea 2017.2
SomeAction.java
SomeAction.java.181 <-- Bunch file for Idea 2018.1

Such fake branches have several advantages for plugin development over classic approach when each IDEA version is stored in a separate branch:

  • Files for each version are available locally. "Compare Files" action in IDE can be used to see the difference in files.
  • Each commit can have own changes for different IDEA-versions.
  • Conflicting problems can be spotted and fixed before commit.
  • No tedious git branch administration.

The main disadvantages are:

  • Bunch files should be removed before building artifacts if build tool tends to pack them into binaries.
  • Bunch files should be processed during commit phase even if there are no conflicts from classic git merge perspective (different parts of file are changed).
This approach works well when number of bunch-files is reasonable small or they never change. 
The best practice is to have bunch files only for solving API compatibility issues, and maintain 
same source for all supported IDEA-versions in other files.

This tool set is used in Kotlin project.

Install

The latest release can be obtained from:

https://github.com/JetBrains/bunches/releases

macOS users can install it via brew:

brew tap jetbrains/utils
brew install bunches

Operations

  • switch - restores state of files for the particular branch. This command is used during the build, and should be used if development with non-based platform is needed.
  • cp - cherry-picks commit to master branch with auto-creating bunch files with given suffix for all affected files.
  • cleanup - removes all bunch files from the repository directory. This command is executed on buildserver to avoid appearing bunch files in result binaries. --ext=<suffix> option can be passed to clean bunch files with the specific extension.
  • check - checks the range of commits for forgotten bunch files.
  • reduce - locates bunch files that are equal to base files (an equality check ignores whitespaces).

.bunch file format

173 // Base branch
// Switch rules
172
as31
as32_181
181
182_181

Each line from switch rules section describes how to switch to the branch mentioned at the beginning of the line. For example for Android Studio 3.2, rule as32_181_173 will be applied (base 173 branch is added implicitly).

Switch tool will do following steps when it gets as32_181_173 as input for each base file in repository:

  • If as32 bunch-file is present, replace base file with it and continue to other file;
  • If 181 bunch file is present, replace base file with it and continue to other file;
  • Leave base version of the file (file from 173 branch) and continue to other file;

bunches's People

Contributors

ausatiy avatar darksidersstrife avatar ddolovov avatar dmiitriyjarosh avatar drazumova avatar goodwinnk avatar ilgonmic avatar stoorx avatar xiexed avatar yanex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bunches's Issues

Smart *cp* command

Make cp understand if the particular file is bunched, and cherry-pick it as is if it's not. Also avoid adding duplicating suffixes, e.g. .as32.as31.

IDE support

  • Actions cp command in IDE
  • Add an IDE action for check command
  • Fix highlighting for Kotlin files (problems with Kotlin resolve)
  • New command and action in IDE for restore origin branch
  • Show only current changes in diffs between main file and bunch file

Find action broken with bunch plugin: exception is thrown while type `bunch` in Find action dialog

Find action broken with bunch plugin: exception is thrown while type bunch in Find action dialog

java.lang.AssertionError
	at com.intellij.openapi.actionSystem.AnActionEvent.getRequiredData(AnActionEvent.java:213)
	at org.jetbrains.bunches.idea.vcs.DiffWithMainAction.getChange(DiffWithMainAction.kt:67)
	at org.jetbrains.bunches.idea.vcs.DiffWithMainAction.isActive(DiffWithMainAction.kt:60)
	at org.jetbrains.bunches.idea.vcs.DiffWithMainAction.update(DiffWithMainAction.kt:56)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareUpdate(ActionUtil.java:167)
	at com.intellij.ide.util.gotoByName.GotoActionModel.updateActionBeforeShow(GotoActionModel.java:303)
	at com.intellij.ide.util.gotoByName.GotoActionModel$ActionWrapper.lambda$getPresentation$0(GotoActionModel.java:647)
	at com.intellij.ide.util.gotoByName.GotoActionModel$ActionWrapper.getPresentation(GotoActionModel.java:651)
	at com.intellij.ide.util.gotoByName.GotoActionModel$GotoActionListCellRenderer.getListCellRendererComponent(GotoActionModel.java:745)
	at com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI$CompositeCellRenderer.getListCellRendererComponent(SearchEverywhereUI.java:964)
	at com.intellij.ui.ExpandedItemListCellRendererWrapper.getListCellRendererComponent(ExpandedItemListCellRendererWrapper.java:38)
	at com.intellij.ui.components.WideSelectionListUI.updateLayoutState(WideSelectionListUI.java:150)
	at java.desktop/javax.swing.plaf.basic.BasicListUI.maybeUpdateLayoutState(BasicListUI.java:1389)
	at java.desktop/javax.swing.plaf.basic.BasicListUI.locationToIndex(BasicListUI.java:1004)
	at java.desktop/javax.swing.JList.locationToIndex(JList.java:1600)
	at java.desktop/javax.swing.JList.getToolTipText(JList.java:1535)
	at com.intellij.ide.IdeTooltipManager.isTooltipDefined(IdeTooltipManager.java:241)
	at com.intellij.ide.IdeTooltipManager.showForComponent(IdeTooltipManager.java:210)
	at com.intellij.ide.IdeTooltipManager.maybeShowFor(IdeTooltipManager.java:196)
	at com.intellij.ide.IdeTooltipManager.eventDispatched(IdeTooltipManager.java:159)
	at java.desktop/java.awt.Toolkit$SelectiveAWTEventListener.eventDispatched(Toolkit.java:2199)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2091)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2090)
	at java.desktop/java.awt.Toolkit.notifyAWTEventListeners(Toolkit.java:2047)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4932)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4858)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4560)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2773)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4858)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:778)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:727)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:751)
	at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:749)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:748)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:911)
	at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.java:849)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:781)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:425)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:690)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:424)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Incorrect behavior in project with multiple VCS roots

Consider the following case:

  • There is a project root with some VCS root and 2 bunch branches: 183 and 191.
  • There is another project nested with a different VCS root and same branches: 183 and 191. Project nested lays inside of root.

bunch command will not work correctly on such configuration.

Examples:

Checkout 2 projects:

git clone https://github.com/ddolovov/bunches-root-project.git root
git clone https://github.com/ddolovov/bunches-nested-project.git root/nested

Check stats in nested:

bunch stats root/nested

Number of affected origin files: 1

Ext   |exists |   del | total
all   |     1 |     0 |     1
183   |     0 |     0 |     0
191   |     1 |     0 |     1
cd ..

Looks correct.

Check stats in root:

bunch stats root

Number of affected origin files: 2

Ext   |exists |   del | total
all   |     2 |     0 |     2
183   |     0 |     0 |     0
191   |     2 |     0 |     2

Error: It counts bunch files in both VCS roots.

Now switch to 191 and check how it works:

bunch switch root 191
git -C root log --oneline

bdcf65e (HEAD -> master) ~~~~ switch 191 ~~~~
3bd9f67 (origin/master, origin/HEAD) Update .gitignore
cd212e4 Initial commit

git -C root status

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Looks good.

What about nested?

git -C root/nested log --oneline

debd5f6 (HEAD -> master, origin/master, origin/HEAD) Initial commit

git -C root/nested status

On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   file-in-nested-project.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	file-in-nested-project.txt.183

no changes added to commit (use "git add" and/or "git commit -a")

Error: Files were switched but there is no commit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.