Journal Système : Un script pour tous les dépots

Posté par (page perso) . Licence CC by-sa
Tags :
18
21
juil.
2013

Ces temps-ci je teste plein de machines, et j'installe régulièrement des stations de travail audio.

Dans le monde de l'audio, c'est l'hystérie en ce moment, et aucune distro n'est à jour des grosses libs qui bougent (lv2 et la tripotie drobilla-lad, entre autres) sans parler des softs eux-mêmes, et au vu du nombre de commits / jour, c'est facile à comprendre.

px-download-install-build-update.sh est un script BASH (>=4) qui, étant donné une liste de dépôts, se charge de les cloner, compiler les programmes qu'ils contiennent, et les mettre à jour subséquemment (et conditionnellement). En l'état, il s'adresse à des utilisateurs de systèmes Debian et dérivés.

Il prétend gérer deux systèmes de versions (Git et SVN), deux systèmes de compilation (Waf et make) et deux modus operandi de make (autogen et configure).

Il permet d'installer les choses séquentiellement (truc avant bidule) ce qui en fait, avec les caractéristiques pré-citées, le gestionnaire de paquets le plus primitif ever :)

Il peut servir pour plein d'autres cas, mais avec les données présentes il permet d'installer un studio audio bleedin-edge pour continuer à rocker le monde libre : si quelqu'un ici souhaite par exemple tester ardour3 dans de bonnes conditions, je lui conseille de considérer ce script.

Il pourrait être plus élégant :
- Je n'ai pas trouvé d'autres moyens de tester si la branche du dépot à bougé, que de greper la sortie du "pull/up". Berk.
- Pour simuler une indexation de tableau associatif, je le vide, je trie les valeurs, et je le re-crée. Grmph.

  • # tableaux associatifs (aka dictionnaires)

    Posté par . Évalué à 9.

    simuler une indexation de tableau associatif

    bash >= 4.2 supporte les tableaux associatifs:

    declare -A assoc_array
    assoc_array=( ["${key1}"]="${value1}" )
    assoc_array+=( ["${key2}"]="${value2}" )
    

    Ça fonctionne aussi pour la déclaration de variables locales :

    foo() {
        local -A assoc_array
        assoc_array=( ["${key1}"]="${value1}" )
        assoc_array+=( ["${key2}"]="${value2}" )
    }
    

    Donc, si tu n'est pas obligé de garder la compatibilité bash 4.1 et antérieurs, tu peux utiliser des tableaux associatifs.

    Hop,
    Moi.

    • [^] # Re: tableaux associatifs (aka dictionnaires)

      Posté par . Évalué à 2.

      Et du coup, j'ai pas dit comment accéder à une entrée du tableau (oops). Rien de bien compliqué :

      foo="${assoc_array["${key}"]}"
      

      Re-hop,
      Re-moi.

      • [^] # Re: tableaux associatifs (aka dictionnaires)

        Posté par (page perso) . Évalué à 9.

        Rien de bien compliqué

        C'te blague. Ya que moi qui trouve ça affreusement illisible ?

        • [^] # Re: tableaux associatifs (aka dictionnaires)

          Posté par (page perso) . Évalué à 6.

          En même temps on parle de bash, c'est franchement pas réputé pour sa lisibilité…

        • [^] # Re: tableaux associatifs (aka dictionnaires)

          Posté par . Évalué à 2. Dernière modification le 22/07/13 à 20:04.

          Sont code est un peu lourd ça peut s'écrire ainsi :

          foo="${assoc_array[${key}]}"

          Et je ne vois pas ce qu'il y a de plus compliqué que tu php :

          foo=$assoc_array[$key]

          Si entourer les identifiants de {} et les variables de "" rend quelque chose « affreusement illisible » alors, je présume que le shell n'est pas fait pour toi, mais ça n'a rien de compliqué. Pour moi c'est un peu comme mettre des parenthèses en maths.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: tableaux associatifs (aka dictionnaires)

            Posté par (page perso) . Évalué à 2.

            Je vois pas ce qu'il y a de plus simple que le go:

            foo := assoc_array[key]
            

            Le problème pour moi est le besoin d'entourer les items de caractères spéciaux, parce que l'usage qu'on veut en faire dans l'énorme majorité des cas n'est pas le besoin rempli par défaut par le langage.

            le shell n'est pas fait pour toi

            En effet, je pense qu'il n'y a pas besoin d'aller plus loin, je reviendrai critiquer quand j'en saurai plus sur le bash :)

      • [^] # Re: tableaux associatifs (aka dictionnaires)

        Posté par . Évalué à 1.

        ouais enfin ça c'est si on stocke des truc à la con dans les variables

        De manière générale

        foo=${assoc_array[$key]}
        

        suffit.

        • [^] # Re: tableaux associatifs (aka dictionnaires)

          Posté par . Évalué à 6.

          ça c'est si on stocke des truc à la con dans les variables

          Ce que feras tout bon utilisateur de ton script dans des cas que tu n'as pas prévus ; par exemple avec une locale différente un message d'erreur contient un espace alors qu'en locale C il n'en contient pas. Ou le chemin contient un espace sur la machine de l'utilisateur, pas chez toi. J'en passe et des meilleures.

          foo=${assoc_array[$key]}
          

          Ne fonctionne pas si "${key}" et/ou "${assoc_array[k]}" contient des caractères spéciaux : espaces, tabulations, \n …

          Et puis il y a un problème de cohérence :
          - pas d'accolades {} pour $key
          - mais accolades pour ${assoc_array[k]}

          Du coup, pour protéger le code des erreurs de l'utilisateur, je protège toutes mes variables entre " et pour la cohérence, je les met toutes entre {}.

          Un peu de coloration syntaxique dans un bon éditeur, et c'est tout de suite lisible.

          YMMV, comme ils disent. ;-)

          Hop,
          Moi.

          • [^] # Re: tableaux associatifs (aka dictionnaires)

            Posté par . Évalué à 3.

            pour la cohérence, je les met toutes entre {}.

            Personnellement ça ne me dérange pas de ne pas en mettre partout. Faire du shell, c'est aussi golfer à chaque ligne :)

            Ça ne rend pas le programme plus fiable, c'est nécessaire uniquement dans des cas précis bien identifié donc je vois pas l'intérêt de surcharger. Donc pour moi :

            foo="${assoc_array[$key]}"

            Mais en shell c'est rare que je fasse autre chose qu'itérer sur un tableau (associatif ou pas).

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: tableaux associatifs (aka dictionnaires)

      Posté par (page perso) . Évalué à 1.

      tu peux utiliser des tableaux associatifs.

      Mais heu, c'est ce que je fais (?). Mon problème est, comme je l'ai écrit dans le journal, de trier mon tableau quand les clefs ne sont pas strictement numériques.

      C'est pour ça que je parlais d'émuler l'indexation (pas l'association).

      Pour faire ça, je n'ai pas trouvé d'autre solution que de sortir les valeurs et les dumper dans un autre tableau en les triant à la volée avec sed et sort :

      declare -A PACKS
      PACKS[00-zero]="zero"
      PACKS[01-one]="one"
      PACKS[02-two]="two"
      PACKS[11-one]="eleven"
      
      PACKS_INDEXES=( ${!PACKS[@]} )
      PACKS_SORTED=( $(echo -e "${PACKS_INDEXES[@]/%/\n}" | sed -r -e 's/^ *//' -e '/^$/d' | sort) )
      
      for PACKAGE in "${PACKS[@]}" ; do
          echo $PACKAGE
      done
      
      echo "----"
      
      for PACKAGE in "${PACKS_SORTED[@]}" ; do
          # echo $PACKAGE
          echo "${PACKS[$PACKAGE]}"
      done
      
      $ ~/tmp/test.sh
      zero
      eleven
      one
      two
      ----
      zero
      one
      two
      eleven

      Et je reste preneur d'une solution plus élégante.

      • [^] # Re: tableaux associatifs (aka dictionnaires)

        Posté par . Évalué à 4.

        Tu as cette manière un peu plus simple :

        #!/bin/bash
        
        declare -A PACKS
        PACKS[00-zero]="zero"
        PACKS[01-one]="one"
        PACKS[02-two]="two"
        PACKS[11-one]="eleven"
        
        readarray -t PACKS_SORTED < <(printf '%s\n' "${!PACKS[@]}" | sort)
        
        for PACKAGE in "${PACKS[@]}" ; do
            echo $PACKAGE
        done
        
        echo "----"
        
        for PACKAGE in "${PACKS_SORTED[@]}" ; do
            # echo $PACKAGE
            echo "${PACKS[$PACKAGE]}"
        done

        Mais c'est plus zoli en zsh (comme toujours) :) :

        #!/bin/zsh
        
        declare -A PACKS
        PACKS[00-zero]="zero"
        PACKS[01-one]="one"
        PACKS[tow]="hello"
        PACKS[02-two]="two"
        PACKS[11-one]="eleven"
        PACKS[one]="coucou"
        
        for PACKAGE in "${(ki@)PACKS}" ; do
            echo "${PACKS[$PACKAGE]}"
        done

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: tableaux associatifs (aka dictionnaires)

        Posté par (page perso) . Évalué à 4. Dernière modification le 23/07/13 à 09:27.

        Mais heu, c'est ce que je fais (?). Mon problème est, comme je l'ai écrit dans le journal, de trier mon tableau quand les clefs ne sont pas strictement numériques.

        C'est pour ça que je parlais d'émuler l'indexation (pas l'association).

        Pour faire ça, je n'ai pas trouvé d'autre solution que de sortir les valeurs et les dumper dans un autre tableau en les triant à la volée avec sed et sort :

        C'est compliqué parceque tu fais une erreur d'utilisation importante — à laquelle te pousse BASH, c'est pour cela que je n'aime pas trop ce shell.

        Quand on programme en shell, on n'utilise pas des variables pour stocker et manipuler des valeurs complexes. On utilise des fichiers, des dossiers et des filtres.

        Ton problème n'est pas du tout que tu utilises sed et sort pour trier tes clefs: au contraire c'est très idoine. Ton problème est que tu utilises un tableau pour stocker ton résultat intermédiaire.

        Tu dois travailler de cette manière:

        packs_query_mock()
        {
        cat <<EOF
        00-zero|zero|Description du package 0
        11-one|eleven|Description du package 11
        01-one|one|Description du package 1
        02-two|two|Description du package 2
        one
        two
        EOF
        }
        
        packs_sort()
        {
           sort -t'|'
        }
        
        packs_select()
        {
           awk -F'|' '{print($2,$3)}'
        }
        
        packs_query_mock | packs_select | packs_sort
        # (Pas testé, pas taper!)

        Si tu dois lire les résultats d'un traitement depuis une fonction shell, tu auras sûrement besoin de IFS.

        La vraie fonction packs_query peut utiliser tous les programmes find etc. pour générer les données.

        La règle n⁰1 de la programmation shell, est que toutes les données complexes sont gérées par les fichiers ou des flux entre deux process, les traitements complexes sont effectués par des outils externes (awk, sed, perl, paste, join, etc.).

        Le champ d'application du shell est la gestion de processus et l'orchestration des traitements, pas le traitement lui-même.

        • [^] # Re: tableaux associatifs (aka dictionnaires)

          Posté par . Évalué à 3.

          La règle n⁰1 de la programmation shell, est que toutes les données complexes sont gérées par les fichiers ou des flux entre deux process, les traitements complexes sont effectués par des outils externes (awk, sed, perl, paste, join, etc.).

          En bourn shell oui, mais ça fait longtemps que les shell qui évoluent (pas le standard POSIX) sont capables de faire bien plus que ça et ce n'est pas le fait que bash ne possède rien directement pour faire du tris qui change la donne.

          Tu peux grandement améliorer la performance d'un script juste en évitant de lui faire utiliser des commandes externes et obtenir le niveau de performance que tu veux sans avoir à réécrire le tout dans un autre langage (c'est à analyser c'est pas une règle d'or, mais ça m'arrive de voir des script passer trop de temps à faire des fork/exec alors que ce n'est pas nécessaire).

          Gérer des fichiers pose aussi le problème du nettoyage. Le builtin trap POSIX n'est pas très pratique pour faire un nettoyage des fichiers (il faut énumérer tous les signaux et s'interdire d'avoir d'autres point de sorti).

          Pour moi toujours passer par des fichiers est une façon de faire, mais de la à dire que c'est LA bonne, je trouve que ça dépend plus de chaque cas.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: tableaux associatifs (aka dictionnaires)

            Posté par (page perso) . Évalué à 2. Dernière modification le 23/07/13 à 15:25.

            Pour moi toujours passer par des fichiers est une façon de faire, mais de la à dire que c'est LA bonne, je trouve que ça dépend plus de chaque cas.

            Oui bien-sûr qu'il n'y a pas de solution universelle, mais depuis que j'ai compris le point de vue que je défend, je trouve la programmation shell bien plus facile, et de plus je n'ai pas l'impression que tout le monde soit bien au courant que c'est la plupart du temps bien plus facile d'organiser les traitements comme je le propose, en passant par des filtres, qu'en bouclant sur des structures de données. Dans la pratique ma position est plus nuancée, bien entendu, mais je trouve souvent plus pertinent de donner aux débutants des avis bien nets que des «oui mais» où le oui et le mais sont structurellement sur un pied d'égalité alors que le mais est complètement anecdotique: je préfère le passer carrément sous silence (dans un premier temps).

            De mon point de vue, le point fort du shell — et le seul intérêt — sont l'accès facile aux programmes, ses opérateurs | et & ainsi que les backquotes. Toute partie du traitement qui ne se décrit pas entièrement en ces termes a intérêt à être déportée dans une sous-routine, éventuellement écrite dans un langage adapté: ce n'est pas parce qu'on écrit une partie d'un programme dans un langage qu'il faut écrire tout le programme dans ce langage. Une fois j'ai fait la grosse erreur d'écrire un gros projet Python pour la seul raison qu'il y avait une lib ESRI à peu-près potable… j'aurais du me contenter d'écrire en Python un adaptateur pour exporter et importer les données dans un format ad-hoc, et utilsier un autre langage pour le reste!

            • [^] # Re: tableaux associatifs (aka dictionnaires)

              Posté par . Évalué à 3.

              De mon point de vue, le point fort du shell — et le seul intérêt — sont l'accès facile aux programmes, ses opérateurs | et & ainsi que les backquotes.

              Je pense que c'est un oublie mais tu as aussi la gestion des fichiers qui est simple (en fait la gestion des descripteurs de fichiers) et c'est ce qui rend le scripting via des fichiers agréables.

              ce n'est pas parce qu'on écrit une partie d'un programme dans un langage qu'il faut écrire tout le programme dans ce langage.

              Oui, il faut tout de même un peu réfléchir (ne pas ajouter un tas de dépendance pour pas grand chose), mais je suis tout à fais d'accord.

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Gestion des dépendances

    Posté par (page perso) . Évalué à 5.

    Est-ce que Nix ne répondrait pas à ton besoin ?

    Sinon pour une gestion de dépendances générique, il y a Ivy.

    http://devnewton.bci.im

  • # Check des modifs d'une branche

    Posté par (page perso) . Évalué à 3.

    Pour git, j'utilise ce genre de test:

       BRANCH=devel
    
       git checkout $BRANCH
       OLDREV=`cat .git/refs/heads/$BRANCH`
       git pull origin $BRANCH
       NEWREV=`cat .git/refs/heads/$BRANCH`
    
       if [ "$OLDREV" != "$NEWREV" ]; then
           # la branche a été modifiée, faisons quelque chose...
    
       fi
    
    • [^] # Re: Check des modifs d'une branche

      Posté par (page perso) . Évalué à 2.

      Bien vu, ça marche. D'autant qu'en l'état, mon grep dégueulbif ne marche que sur des systèmes en anglais, je viens de percuter en testant ton truc. Merci !

      Maintenant, il me reste à trouver une procédure pour SVN (et pour BZR et mercurial :|).

      J'ai regardé, apparemment svn ne stocke pas d'infos localement sur l'état de la branche (seulement le nombre de fichiers..?) à part peut-être dans .svn/wc.db (binaire) un truc serait d'arriver à mettre la sortie de svn log dans une variable, puis de faire pareil après un svn up, puis de comparer les deux variables, mais comment faire ça sans passer par un fichier ?

      • [^] # Re: Check des modifs d'une branche (Auto-réponse Linus-style)

        Posté par (page perso) . Évalué à 3. Dernière modification le 22/07/13 à 15:06.

        comment faire ça sans passer par un fichier ?

        Like this, you pathetic worthless waiste of oxygen :

        svn_pre=$(svn log)
        svn up
        svn_post=$(svn log)
        
        if [ "$svn_pre" != "$svn_post" ]; then
            echo "moved!"
        else
            echo "didn't move!"
        fi
      • [^] # Re: Check des modifs d'une branche

        Posté par (page perso) . Évalué à 4.

        Pour svn, je ferais bien un svn info, suivit de ce qu'il faut pour récupérer la révision affichée. Mais ça ne change pas beaucoup de ce que tu fais…

        svn info # pour savoir la revision locale et récupérer url-depot-distant -> faire un grep ou je ne sais quoi
        svn info url-depot-distant  # pour savoir la revision distante
        # comparer les deux révisions
        
      • [^] # Re: Check des modifs d'une branche

        Posté par (page perso) . Évalué à 3.

        Bien vu, ça marche. D'autant qu'en l'état, mon grep dégueulbif ne marche que sur des systèmes en anglais, je viens de percuter en testant ton truc. Merci !

        Tu peux créer des fonctions auxilaires genre
        sh
        myproject_grep()
        {
        env LANG=C grep "$@"
        }

        Ceci dit, c'est sûrement plus simple de changer LANG en C dans ton script, même si c'est un poil moins propre.

        Tu peux aussi sauver la valeur de LANG, exporter LANG=C et envelopper les fonctions dont la sortie est montrée à l'utilisateur dans des délégations similaires à la précédente.

    • [^] # Re: Check des modifs d'une branche

      Posté par . Évalué à 2.

      Si le but est simplement de vérifier que la révision à changée, autant faire un git fetch simple et regarder le fichier .git/refs/remotes/origin/master (ou autre). git pull est plus lent parce qu'il fait un merge (c'est un fast-forward, donc c'est rapide) et un checkout (super-super lent avec des gros projets).

      Mais bon, là étant donné qu'il faut de toute façon compiler la branche si elle change, il faudra forcement faire un checkout un jour ou l'autre.

      • [^] # Re: Check des modifs d'une branche

        Posté par . Évalué à 2.

        Lors de clones un --depth 1 permet d'être plus rapide aussi, non ?

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Vendredi style

    Posté par . Évalué à 10.

    Tu viens d'implémenter le système de paquets AUR d'Archlinux dans Debian.

    • [^] # Re: Vendredi style

      Posté par . Évalué à 1.

      J''etais sur le point de faire la meme avec Portage, de Gentoo. -_-

    • [^] # Re: Vendredi style

      Posté par . Évalué à 1. Dernière modification le 22/07/13 à 14:15.

      Arch/AUR se prête excessivement bien à la mise en place d'un environnement de production audio dernier cri :
      - noyau patché RT prêt à être compilé (linux-rt, rtirq)
      - versions récentes des logiciels (Jack2, DAW, instruments virtuels…)
      Seul bémol, il faut disposer d'un peu de temps processeur pour tout compiler !

      • [^] # Re: Vendredi style

        Posté par (page perso) . Évalué à 2.

        Mais les dépôts AUR, sont linkés aux dépôts des projets d'une façon ou d'une autre ? Ah, je comprends, tu ajoutes tes dépôts, et ils sont gérés… Je suppose qu'il y a des tests… Oui, c'est vrai, ça fait envie.

      • [^] # Re: Vendredi style

        Posté par . Évalué à 0.

        Ubuntu Studio ne répond pas à ce besoin ?

        "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

        • [^] # Re: Vendredi style

          Posté par (page perso) . Évalué à 1.

          Non.

          • [^] # Re: Vendredi style

            Posté par . Évalué à 0. Dernière modification le 22/07/13 à 20:11.

            Pourquoi ?
            - noyau rt
            - logiciels relativement récents (au pire, y'a sûrement des PPA)
            - tout ce qu'il faut pour "faire du son" (ardour, …) a priori
            - rien à compiler

            "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

            • [^] # Re: Vendredi style

              Posté par (page perso) . Évalué à 2.

              Relativement récent, en ce moment ça le fait pas ; quand je rapporte un bug, j'ai besoin d'être sur que les versions sont à jour. Exemple, Qtractor :

              • Ubuntu : Version: 0.5.7-1
              • Current : Version: 0.5.10

              Quant à Ardour, la 3.0 n'est encore packagée nulle part, que je sache.

              Et j'aime bien compiler, ça me permet de voir comment sont faits les programmes que j'utilise.

    • [^] # Re: Vendredi style

      Posté par . Évalué à 2.

      Comment sont gérés les mises à jour ? Je veux dire à l'installation tu as la dernière version du dépôt. Comment le gestionnaire choisi de réexecuter la tambouille ?

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # mr

    Posté par . Évalué à 4.

    Je viens de découvrir l'utilitaire mr qui permet de gérer plusieurs dépôts à l'aide d'une seule commande.

    En configurant le tout, je pense qu'il est aussi possible de placer les commandes qui vont bien pour compiler en fonction du dépôt.

  • # Update

    Posté par (page perso) . Évalué à 1.

    Ce script est maintenant unifié dans un autre script.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.