An intelligent diff tool for the output of Gradle's dependencies task

Overview

Dependency Tree Diff

An intelligent diff tool for the output of Gradle's dependencies task which always shows the path to the root dependency.

 +--- com.squareup.sqldelight:android-driver:1.4.0
 |    +--- com.squareup.sqldelight:runtime-jvm:1.4.0
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72
-|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0
+|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.4.0 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72 -> 1.4.0
-|    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+|    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)
 \--- com.squareup.sqldelight:rxjava2-extensions:1.4.0
-     \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+     \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)

Unlike a normal diff, unchanged entries are displayed only when they are a parent dependency to one that changed.

Compare the above diff to diff -U 0:

@@ -31,3 +31,3 @@
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72
-|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0
+|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.4.0 (*)
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72 -> 1.4.0
@@ -35 +35 @@
-|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)
@@ -40 +40 @@
-|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)
@@ -51 +51 @@

Note how there is no context as to what is affected.

In this particular sample we can reach the root dependencies with diff -U 2:

@@ -29,14 +29,14 @@
 +--- com.squareup.sqldelight:android-driver:1.4.0
 |    +--- com.squareup.sqldelight:runtime-jvm:1.4.0
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72
-|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0
+|    |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.4.0 (*)
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72 -> 1.4.0
 |    +--- androidx.sqlite:sqlite:2.1.0 (*)
-|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)
 |    \--- androidx.sqlite:sqlite-framework:2.1.0 (*)
 +--- com.squareup.sqldelight:rxjava2-extensions:1.4.0
 |    +--- com.squareup.sqldelight:runtime:1.4.0
 |    |    \--- com.squareup.sqldelight:runtime-jvm:1.4.0 (*)
-|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 (*)
+|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72 -> 1.4.0 (*)
 |    \--- io.reactivex.rxjava2:rxjava:2.2.5 -> 2.2.19 (*)
 \--- com.squareup.inject:inflation-inject:0.5.1
@@ -49,4 +49,4 @@

Now, however, additional unchanged dependencies are displayed such as androidx.sqlite and the SQLDelight runtime dependency by the RxJava 2 extensions artifact.

For deep dependency chains, -U 2 will not be enough to see all of the roots. Increasing the value will only show more unchanged dependencies. dependency-tree-diff will always display the minimal subset needed to provide context.

For more information about why a diff of the dependency tree is useful see "Surfacing Hidden Change to Pull Requests". To learn about how code shrinking keeps the binary as small as possible see "Shrinking a Kotlin binary by 99.2%".

Usage

The tool parses the output of Gradle's dependencies task. Specify --configuration <name> when running the task so that only a single tree will be shown.

$ ./gradlew :app:dependencies --configuration releaseRuntimeClasspath > old.txt
$ # Update a dependency...
$ ./gradlew :app:dependencies --configuration releaseRuntimeClasspath > new.txt
$ ./dependency-tree-diff.jar old.txt new.txt

See src/test/fixtures/ for example outputs and their expected diffs.

Install

Mac OS

$ brew install JakeWharton/repo/dependency-tree-diff

Other

Download standalone JAR from latest release. On MacOS and Linux you can chmod +x and execute the .jar directly. On Windows use java -jar.

License

Copyright 2020 Jake Wharton

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Support all different OS line endings

    Support all different OS line endings

    Some tests were failing because

    		val coordinateStart = dependencyLine.indexOf("--- ")
    		check(coordinateStart > 0) {
    			"Unable to find coordinate delimiter: $dependencyLine"
    		}
    

    was throwing up on dependencyLine == "\r".

    Additionally

    • bump minor versions (there were security warnings, but also just to be on latest.)
    • add tests to CI, otherwise they might get broken again

    Tests

    I used the IDEA line ending chooser to verify and set the line endings for each file. image

    The expected.txts are all using LF ending as there's a hardcoded \n in buildString.

    I double-checked that the line endings are good in git by downloading the .ZIP file and looking in HEX editor. image

    opened by TWiStErRob 1
  • Fix task dependencies between r8Jar and fatJar

    Fix task dependencies between r8Jar and fatJar

    I noticed that after changing Kotlin source files, Gradle thought the r8Jar task was up-to-date. This change uses the output files of the fatJar task as an input to the r8Jar task. The task dependency can be inferred by Gradle, the input / output dependency cannot.

    opened by drewhannay 1
  • Don't show diff for common subtrees

    Don't show diff for common subtrees

     +--- com.google.firebase:firebase-perf:18.0.0
    -|    \--- com.squareup.okhttp3:okhttp:3.0.0 -> 4.8.0
    -|         +--- com.squareup.okio:okio:2.7.0
    -|         |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.70 -> 1.3.72 (*)
    -|         |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70 -> 1.3.72
    -|         \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
    +|    \--- com.squareup.okhttp3:okhttp:3.0.0 -> 4.8.1
    +|         +--- com.squareup.okio:okio:2.7.0
    +|         |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.70 -> 1.3.72 (*)
    +|         |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70 -> 1.3.72
    +|         \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
    

    should be

     +--- com.google.firebase:firebase-perf:18.0.0
    -|    \--- com.squareup.okhttp3:okhttp:3.0.0 -> 4.8.0
    +|    \--- com.squareup.okhttp3:okhttp:3.0.0 -> 4.8.1
     |         +--- com.squareup.okio:okio:2.7.0
     |         |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.70 -> 1.3.72 (*)
     |         |    \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70 -> 1.3.72
     |         \--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 (*)
    

    assuming we want to show subtrees for changed nodes.

    Otherwise we just show it as a changed leaf.

    bug 
    opened by JakeWharton 1
  • Produce a minimal fat jar with R8

    Produce a minimal fat jar with R8

    Not really blocked on https://youtrack.jetbrains.com/issue/KT-41304, but it would be nice to not need to fetch the annotations artifact to prevent warnings.

    opened by JakeWharton 1
  • Support single dependency on a configuration

    Support single dependency on a configuration

    Some configurations have only a single dependency, they don't start with +---, but instead with \---.

    See test for example:

    • old.txt is a standard gradlew :module:dependencies --configuration=detekt
    • new.txt is the same, but with an additional detekt("org.jetbrains.kotlin:kotlin-stdlib:1.6.21") in build.gradle to get some differences.

    Note: this might conflict with #11 because the regex and the filter are adjacent.

    opened by TWiStErRob 0
  • Question: How do you handle baselining the original dependency tree?

    Question: How do you handle baselining the original dependency tree?

    This tool great, thanks for creating it.

    I'm curious where you get the baseline dependency output that you compare the new dependency output? My thought was to have the ability for someone to re-baseline when a change occurred, and to keep the dependencies output under source control. That way you'd always see the diff in git, and you'd have something to compare to.

    Thank you!

    opened by handstandsam 0
  • Support multiple configurations in one diff

    Support multiple configurations in one diff

    Allow gradlew :module:dependencies > deps.txt to be the input to the program. Also includes some fixes from #11 and #12, but I think those will get merged first.

    Solution

    Originally the "dependency list" was created by looking between +--- and an empty line. I've extended this to look for the starting token +---, then peek before to find the configuration name (and sometimes description). Then create a map of (configuration, diff), and produce a nice output.

    Note: all expected.txts had to change because it now outputs which configuration is being diffed, even when there's only one.


    Examples where configurations and dependencies change
    (gradlew :dependencies on this project with different version of Gradle and Kotlin):

    The unit tests include gradle742-kotlin14.txt and gradle742-kotlin15.txt diff (configuration-differences) as well as a diff of one of my projects when updating Dagger which affects compile, runtime and kapt classpaths (multiple-configurations).

    opened by TWiStErRob 7
  • Added flatten diff support

    Added flatten diff support

    In real project we often need to detect libraries updates without deep dive into dependency tree. I've added support of printing diff as lists of changed, added and removed libraries.

    Also I've added command to transform dependencies tree to flat dependencies list.

    opened by KarenkovID 0
  • Upgrade Dependencies and use Path extensions

    Upgrade Dependencies and use Path extensions

    The project has been stuck on 1.4 for a bit, updating is probably helpful and it only uses 5 KB extra.

    Also because of the higher Kotlin version the new Path extensions can be used, do note though that the default readText isn't optimized enough, and so a custom version was needed.

    opened by kyay10 1
Releases(1.2.0)
Owner
Jake Wharton
Jake Wharton
A tool to validate text inside TextInputLayout

Download dependencies { implementation 'com.github.anderscheow:validator:2.2.1' } Usage Available rules LengthRule MaxRule MinRule NotEmptyRule NotN

Anders Cheow 129 Nov 25, 2022
An easy-to-use, cross-platform measurement tool that pulls data out of CD pipelines and analysis the four key metrics for you.

Maintained by SEA team, ThoughtWorks Inc. Read this in other languages: English, 简体中文 Table of Contents About the Project Usage How to Compute Contrib

Thoughtworks 277 Jan 7, 2023
recompose is a tool for converting Android layouts in XML to Kotlin code using Jetpack Compose.

recompose is a tool for converting Android layouts in XML to Kotlin code using Jetpack Compose.

Sebastian Kaspari 565 Jan 2, 2023
Utility tool to make you a computer ninja.

Cmd Window Never spend 6 minutes doing something by hand when you can spend 6 hours failing to automate it - Zhuowej Zhang What is this about? This to

Marcin Radoszewski 3 Feb 1, 2022
BinGait is a tool to disassemble and view java class files, developed by BinClub.

BinGait Tool to diassemble java class files created by x4e. Usage To run BinGait, run java -jar target/bingait-shadow.jar and BinGait will launch. If

null 18 Jul 7, 2022
A command line tool for NFT stuff

MartaKli is a command line tool to help you generate your NFT pfp project. Current features: Generate batch of images using different layers and corre

Martabak Cult 2 Oct 4, 2022
KDoctor - A command-line tool that helps to set up the environment for Kotlin Multiplatform Mobile app development

KDoctor is a command-line tool that helps to set up the environment for Kotlin Multiplatform Mobile app development.

Kotlin 331 Dec 29, 2022
Tool to look for several security related Android application vulnerabilities

Quick Android Review Kit This tool is designed to look for several security related Android application vulnerabilities, either in source code or pack

LinkedIn 2.9k Jan 2, 2023
A Simple Todo app design in Flutter to keep track of your task on daily basis. Its build on BLoC Pattern. You can add a project, labels, and due-date to your task also you can sort your task on the basis of project, label, and dates

WhatTodo Life can feel overwhelming. But it doesn’t have to. A Simple To-do app design in flutter to keep track of your task on daily basis. You can a

Burhanuddin Rashid 1k Jan 1, 2023
Gradm (Gradle dependencies manager) is a new way to manage dependencies easier and more efficient.

Gradm (Gradle dependencies manager) is a new way to manage dependencies easier and more efficient.

null 16 Jan 9, 2023
andle is an Android tool help you sync dependencies, sdk or build tool version.

andle andle is an Android tool to help you sync dependencies, SDK or build tool version. Installation Simple install by pip: $ sudo pip install andle

Jintin 58 Sep 17, 2022
A simple utility to remove unused resources in your Android app to lower the size of the APK. It's based on the Android lint tool output.

android-resource-remover android-resource-remover is utility that removes unused resources reported by Android Lint from your project. The goal is to

Keepsafe 1.3k Dec 16, 2022
LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

马天宇 829 Dec 29, 2022
ShapeShift️ - A Kotlin library for intelligent object mapping and conversion between objects

ShapeShift️ A Kotlin library for intelligent object mapping and conversion between objects. Documentation Installation Maven Gradle Groovy DSL Kotlin

KRUD 127 Dec 7, 2022
Multiplaform kotlin library for calculating text differences. Based on java-diff-utils, supports JVM, JS and native targets.

kotlin-multiplatform-diff This is a port of java-diff-utils to kotlin with multiplatform support. All credit for the implementation goes to original a

Peter Trifanov 51 Jan 3, 2023
The powerfull Diff Util in Android Recycler View

DiffUtil The powerfull Diff Util in Android Recycler View What is RecyclerView ? RecyclerView is flexible and efficient version of ListView. It is an

Lloyd Dcosta 1 Sep 30, 2021
An android open-source quick search/diff/download plugin.

Android Reference Intellij Plugin This library based on AndroidSourceViewer It's built with the Gradle and rewritten by kotlin, that's why it's a new

haoxiqiang 3 Nov 2, 2022
ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, create architecure fitness functions, and anaysis system dependencies..

ArchGuard backend ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, database, create ar

ArchGuard 446 Dec 20, 2022
Minimal example of how to safely share a file produced by a task in one project, with a task in another project.

How to share files across Gradle subprojects: A minimal example This is the Gradle project: . ├── producer │ └── build.gradle.kts ├── consumer │ └

Rob Moore 2 Dec 17, 2021
Flixbus-task - Android Coding Task from FlixBus

FlixBus Coding Task Features Fetch timetables from FlixBus service Show fetched

Ali Ansari 0 Jan 23, 2022