Pas très nouveau non-plus mais ce billet présente très bien ces différentes sources qui en effet contiennent de vrai petits (ou grands) bijoux.
Comme il dit pas un scoop mais toujours intéressant.
De plus en plus de développeurs C s'éloignent du standard C89 avec entre autres l'avènement de C11. Il serait en effet facile d'imaginer qu'au minimum C99 soit raisonnablement bien répandu 15 ans plus tard. Mais c'est sans compter Microsoft Visual C++.
Microsoft ne supporte pas C99 avec MSVC. Même au niveau de la bibliothèque standard des fonctions qui leur serait pourtant assez facile de fournir n'existent pas, et leur équivalent n'est pas exactement équivalent.
Prenons l'exemple amusant (ou pas) de snprintf()
. Cette variante plus sûre de sprintf()
a en effet été standardisée dans C99. De son côté, MSVC fournit différentes variantes de fonctions qui ressemblent, dont _snprintf()
. Elles ressemblent suffisamment pour qu'un développeur naïf ajoute quelque chose comme #define snprintf _snprintf
pour compiler avec MSVC, mais ces fonctions ont de subtile différences qui peuvent se révéler ennuyeuses, voire pire, dangereuses.
Par exemple, C99 dit que snprintf()
retourne le nombre d'octets qui auraient été écrits si le buffer avait été suffisamment grand. Une astuce pratique qui repose sur cette propriété (via la variante vsnprintf()
) est de calculer la taille nécessaire pour un buffer avec vsnprintf(NULL, 0, fmt, ap)
¹ pour l'allouer ensuite. Mais _snprintf()
de MSVC retourne -1
si le buffer est trop petit.
C99 dit aussi que snprintf()
écrit toujours le \0
final si la taille du buffer est > 0, même si la sortie est tronquée par ce que le buffer est trop petit. Mais _snprintf()
de MSVC n'écrit le \0
final que si la sortie n'a pas été tronquée. Cette différence est dangereuse pour un habitué du comportement de C99, car il est alors courant de ne pas vérifier la valeur de retour de snprintf()
: même si ce n'est pas parfait, dans la pratique si l'appel est correct (format valide et arguments appropriés) snprintf()
réussira toujours. Au pire la sortie sera tronquée, mais rien de plus grave. Avec le comportement de _snpritnf()
par contre si la sortie est tronquée, utiliser le buffer peut être dangereux puisque il n'a pas de \0
final, et donc les fonctions de manipulation de chaînes ne qui ne prennent pas d'argument de taille vont lire au delà de la fin du buffer.
Tout ceci rend l'utilisation de snprintf()
assez difficile si l'ont veut supporter MSVC. Il y a bien sûr différentes solutions. La plus évidente est de ne pas dépendre du comportement de C99 et de toujours vérifier la valeur de retour. Si tous les appels vérifient que la valeur de retour n'est pas négative, et même si le comportement sera différent avec MSVC si la sortie est tronquée, il n'y a pas de risques puisque _snprintf()
retourne -1
lorsque la sortie est tronquée. Cependant cette solution peut impliquer beaucoup de petits changements ennuyeux, et a un comportement différent sous MSVC. De plus, il y a fort à parier que si snprintf()
a été utilisé dans le passé il le sera encore dans le futur, et il faudra donc toujours penser au comportement différent sous MSVC.
Une autre solution évidente, bien que plus compliquée, est d'écrire un wrapper pour fournir une version de snprintf()
qui se comporte comme C99 le demande. Avec _vsnprintf_s(buf, count, _TRUNCATE, fmt, ap)
et _vscprintf()
il reste assez simple d'écrire ce wrapper, même s'il faut faire attention aux détails de ces API (par exemple _vsnprintf_s()
n'accepte pas un count de 0).
Enfin bref, tout ça pour dire qu'il semble que C89 a encore de beaux jours devant lui, tout comme les bibliothèques qui fournissent une compatibilité C99 (et plus si affinité).
¹ Pour être complètement honnête, les implémentations pre-C99 de snprintf()
ont pour la plupart de subtiles différences, comme par exemple SUSv2 qui n'autorise pas count à être 0. C'est pour ça que l'ont voit souvent une variante avec un buffer de taille 1 :
char dummy;
int len = vsnprintf(&dummy, 1, fmt, ap);
Avec l'option -x
de less, il est possible de définir la position des fins de tabulations (tab stops). C'est fort pratique pour visualiser un fichier qui utilise des tabulations d'une largeur différente de 8 (la valeur par défaut), avec par exemple less -x4
.
Encore mieux, il est possible de spécifier plusieurs positions, ce qui est très utile par exemple pour visualiser un diff d'un fichier contenant des tabulations : en effet, comme chaque ligne d'un diff contient un caractère de contrôle en plus (+, - ou espace), les tabulations peuvent ne plus être alignées (si par exemple une tabulation de 8 commençait à l'offset 7, elle commencera alors à l'offset 8… et terminera alors à 16).
Et donc pour ce cas, il suffit de définir une première largeur de 9 (8 + le caractère de contrôle de diff), puis une de 8 : less -x9,17
.
Et bien sûr c'est fort pratique pour Git : si la majeure partie des sorties de Git qui contiennent des tabulations que vous consultez sont des diffs (ce qui est fort probable), définir core.pager
à less -x9,17
(ou autre valeur appropriée à votre projet) permet d'avoir des tabulations bien alignées sans avoir à définir PAGER à la main pour chaque appel.
À noter bien sûr que cette propriété de configuration peut être aussi bien définie dans votre ~/.gitconfig global que le .git/config d'un dépôt particulier (très pratique si un projet particulier utilise un largeur de tabulation différente de 8).
Après vous être pris la tête pendant un bon moment à voir « le patch ne s'applique pas », vous vous rendrez compte que git am
supprime les CR par défaut.
J'imagine que le but est de simplifier la vie des gens qui reçoivent des patchs par email (puisque la fin de ligne pour les mails est CR-LF) et que la plupart des fichiers utilisent seulement LF.
Moins pratique par contre si l'on a utilisé git format-patch
et qu'un des fichiers avait des CR-LF.
Solution : passer l'option --keep-cr
à git-am.
Et encore une vidéo sympa (heh) sur la neutralité du net. Bien plus frivole que la précédente bien sûr, vous avez vu le titre. Presque SFW -- la neutralité du net est SFW donc la question ne se pose même pas.
Merci karchnu pour le lien :)
Edit : quelques remarques pertinentes de quelqu'un de pertinent : http://shaarli.guiguishow.info/?BYFLwQ
Mais moi je suis naïf est pense/espère que des choses comme ça peuvent éveiller un intérêt chez certains pour se poser la question des détails et enjeux. Oui, je suis optimiste.
Bon je sais que c'est #old, mais je ne l'avais pas lié et ça vaut le coup.
Apparemment déjà quelqu'un s'est dit que c'était malin de mettre les logs de Xsession (donc que qu'on avait dans ~/.xsession-errors) dans /var/log/{messages,syslog,user.log}. Oui, les trois tant qu'à faire.
Enfin bref, déjà ça avait pas l'air super malin dit comme ça, mais quid de quand une application lancée par la session part en vrille et affiche tout un tas de bousin dans stderr ? Sans surprise, ces trois fichiers grossissent à vue d'œil.
Les miens ont atteint 320M chacun avant que je ne trouve et tue le programme incriminé (et encore, je m'en suis rendu compte dans la minute), ce qui m'a bouffé à peu de choses près 1G dans /var (je n'ai pas de /var, donc dans /). Et même si je n'ai pas vérifié, je pense que vu que le logger (journald) est un service système, il va avoir tous les droits pour utiliser les blocs réservés et donc remplir le FS à s'en rendre malade.
Ah le bon vieux temps où une telle chose n'aurait rempli "que" $HOME…
Enfin bref, le plus intéressant dans l'histoire est que si j'en crois la documentation de journald.conf, le comportement par défaut est de ne pas logguer les sessions avec le système. Mais ma conf de journald (celle par défaut dans Debian testing/unstable) est vide (tout est commenté) et devrait j'imagine utiliser les valeurs par défaut… enfin bref j'ai tenté de définir manuellement SplitMode=uid
, on verra ce que ça donne.
Bref, je ne sais pas à qui revient vraiment la faute (journald tout pourri ou mauvaise conf dans Debian ?), mais le résultat est le même, mes logs on été pourris par une application bénigne en userspace qui est partie en vrille (comme le font et vont le faire les apps userspace). Et quid d'un petit malin qui fait ça exprès.
La suite (peut-être) au prochain numéro.
Je savais qu'on pouvait tout faire, mais bowdel !
Lire aussi la section suivante pour les plages : http://git-scm.com/docs/git-rev-parse#_specifying_ranges
A simple way to force Firefox/Iceweasel to clear its local DNS cache.
Ça a l'air d'une opération toute bête, mais utiliser Icedove comme client de flux Atom/RSS en provenance de sites HTTPS non vérifiés par une autorité installée est très subtil. Simplement essayer d'ajouter le flux ne va pas marcher avec le très subtil et mensonger message d'erreur « L'adresse de flux est introuvable ».
L'utilisateur naïf va tenter d'importer le certificat dans les préférences après avoir vérifié trois fois que son adresse est correcte, mais c'est sans compter que comme Firefox, il n'utilise que le CN pour les exceptions manuelles [1].
Donc, pour ajouter une exception qui marche, on va procéder en deux étapes :
Vraiment subtil mais ça marche.
[1] Ou même que ça ne marche pas du tout, je ne suis pas sûr puisque ça n'a pas ajouté d'entrées dans le fichier d'exceptions. Enfin bref.
Je le savais déjà, mais c'est quand-même beau.
hg n'a pas directement le format-patch
de Git, qui est très pratique non seulement pour envoyer des patches par mail (où hg a l'extension Patchbomb), mais aussi pour simplement exporter vers un fichier par exemple pour attacher à un rapport de bug.
hg a export
qui fait le boulot, mais qui n'écrit pas automatiquement dans un fichier. Pour ce faire, il faut utiliser -o
(--output
), et écrire un nom de fichier à la main. Heureusement on peut utiliser des des formats automatisés comme %n
et %m
. Pour une sortie similaire à format-patch
on utilisera -o '%n-%m.patch'
.
Comme tout ça est bien verbeux, je suggère un alias (http://www.selenic.com/mercurial/hgrc.5.html#alias) :
[alias]
format-patch = export -v -o '%n-%m.patch'
[defaults]
dans l'hgrc
permet de configurer les options par défaut des différentes commandes, comme par exemple -vf
pour log
.
Les branches sous Git sont réputées pour êtres différentes de celles des autres systèmes, et c'est vrai. La fonctionnalité de hg la plus proche de celle des branches Git sont les bookmarks
.
Pas évident de prime abord, mais ça marche plutôt bien (au moins pour un utilisateur occasionnel venant de Git).
Le comportement par défaut du log
de hg est proprement exaspérant pour un utilisateur de Git : la révision par défaut étant tip:0
(qui n'est pas nécessairement l'état courant).
Pour avoir le log de l'état courant du dépôt, comme le fait Git par défaut : -f
(--folow
). On ajoutera -v
pour avoir des messages complets.
Pour inclure les différences on utilisera p
, comme avec Git (peut-être en combinaison avec -g
pour avoir le format étendu de Git, même s'il ne change rien pour les diffs les plus courants).
Un autre must-have, le pendant du color
de Git, et fonctionne à peu près pareil.
Must-have, particulièrement pour tout utilisateur de Git qui a l'habitude d'un comportement pratique par défaut. Comme son nom l'indique, cette extension permet d'utiliser un pager automatiquement sur la sortie de la plupart des commandes, comme par exemple log
ou export
.
Les options suggérées pour less sont très bonnes, et fonctionnent comme Git :
F : quitter less automatiquement si la sortie tient sur l'écran
R : garder les séquences d'échappement pour la coloration (utile en particulier avec l'extension color)
X : ne pas vider la vue à la sortie, indispensable quand on utilise F
Quand on importe un certificat auto-signé dans Firefox, il ne s'applique qu'à un seul sous-domaine particulier (celui d'où on l'a importé si on a ajouté une exception, ou le CN si on l'a importé dans le gestionnaire). C'est bien, mais quand il y a plusieurs sous-domaines (ou domaines) qui utilisent le même certificat (via un subjectAltName), ça devient vite ennuyeux de refaire la même manip' pour chaque sous-domaine (et de les vérifier tous).
Heureusement, il y a une astuce : modifier le fichier cert_override.txt dans le dossier du profil. Il vaut mieux d'abord avoir ajouté une exception (et non uniquement avoir importé le certificat) pour avoir une entrée à dupliquer aisément. Il suffit ensuite de dupliquer la ligne appropriée dans ce fichier et de changer le domaine (1ère entrée), puis de relancer Firefox.