import numpy as np import matplotlib.pyplot as plt from matplotlib.patheffects import Stroke, Normal forges = { "Trac" : [ (2004, 2024, "C0") ], "Redmine" : [ (2006, 2024, "C0") ], "SourceForge": [ (2000,2002,"C2"), (2002,2002,"C2"), (2002,2012,"C1")], "GForge": [ (2002, 2009, "C5"), (2009, 2009, "C5"), (2009, 2024, "C1") ], "FusionForge" : [ (2009, 2018, "C5"), (2018, 2024, ".75") ], "Allura": [ (2009,2024,"C7") ], "GitLab" : [ (2011, 2013, "C4"), (2013, 2024, "C3")], "Tuleap" : [ (2011, 2024, "C0") ], "Gogs": [ (2014, 2024, "C0"), (2016, 2016, "C0"), (2016, 2024, "C0")], "Gitea": [ (2016, 2022, "C0"), (2022, 2022, "C0"), (2022, 2024, "C1") ], "Forgejo": [ (2022, 2024, "C0") ], "SourceHut": [ (2018, 2024, "C6") ], "Gitorious" : [ (2009, 2015, "C0") ], "sourceforge.net" : [ (1999, 2012, "C2"), (2012, 2024, "C7") ], "forge.objectweb.org" : [ (2002, 2003, "C2"), (2003, 2007, "C5"), (2007, 2007, "C5") ], "forge.ow2.org" : [ (2007, 2018, "C5"), (2018, 2018, "C5") ], "gitlab.ow2.org" : [ (2017, 2024, "C3") ], "gforge.inria.fr": [ (2005, 2021, "C5"), (2021,2021, "C5") ], "gitlab.inria.fr": [ (2016, 2024, "C3") ], "forge.imag.fr": [ (2009, 2016, "C5"), (2016,2016, "C5") ], "gricad‐gitlab.univ‐grenoble‐alpes.fr": [ (2016, 2024, "C3") ], "gitlab.huma-num.fr": [ (2016, 2024, "C3") ], "sourcesup.renater.fr" : [ (2004, 2024, "C5") ], "code.google.com" : [ (2007, 2014, "C1") ], "bitbucket.org" : [ (2008, 2024, "C1") ], "github.com" : [ (2008, 2024, "C1") ], "gitlab.com" : [ (2012, 2014, "C4"), (2014, 2024, "C3") ], "sr.ht": [ (2018, 2024, "C6") ] } figure = plt.figure(figsize=(10,7)) ax = plt.subplot(1,1,1) for i, (name, segments) in enumerate(forges.items()): text = ax.text(segments[0][0], i, name+" ", horizontalalignment="right", verticalalignment="center") text.set_path_effects([Stroke(linewidth=2.5, foreground="white"), Normal()]) for (start, stop, color) in segments: X = [start, stop] Y = [i,i+1] if start == stop else [i,i] ax.plot(X, Y, marker="o", color=color, linewidth=2) ax.plot(X, Y, linestyle="", marker="o", color="white", markersize=3) xticks = np.arange(1998, 2024, 2) labels = [f"{year}" if year != 2004 else "2004\ngit " for year in xticks] ax.set_xticks(xticks) ax.set_xticklabels(labels) ax.set_xlim(1998,2023.1) ax.set_yticks([]) # Line for git creation in 2004 ax.axvline(2004, color="black", zorder=-1, linestyle=":") ax.spines["right"].set_visible(False) ax.spines["left"].set_visible(False) ax.spines["top"].set_visible(False) # ax.spines["bottom"].set_visible(False) ax.grid(lw=.25, ls="-", color="black", alpha=.25) # Legend from matplotlib.lines import Line2D lines = [Line2D([0], [0], color="C0", lw=4), Line2D([0], [0], color="C1", lw=4), Line2D([0], [0], color="C2", lw=4), Line2D([0], [0], color="C3", lw=4), Line2D([0], [0], color="C4", lw=4), Line2D([0], [0], color="C5", lw=4), Line2D([0], [0], color="C6", lw=4), Line2D([0], [0], color=".75", lw=4)] ax.legend( lines, ['Logiciels libres', 'Logiciels non libres', 'Forge originale', 'GitLab (projets publics)', 'GitLab (projets privés)', 'GForge/FusionForge', 'SourceHut', 'Plus de nouvelle version'], edgecolor="None", ncol=len(lines)//2, loc="upper left", bbox_to_anchor=(0, 1.1), borderaxespad=0) plt.savefig("forge-timelines.png") # plt.show()