<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:gd="http://schemas.google.com/g/2005" xmlns:georss="http://www.georss.org/georss" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-2161762455502736718</atom:id><lastBuildDate>Fri, 21 Aug 2026 11:01:00 +0000</lastBuildDate><category>programming</category><category>linux</category><category>fedora</category><category>ruby</category><category>gaming</category><category>git</category><category>configuration</category><category>hardware</category><category>kindle</category><category>science</category><category>food</category><category>google</category><category>homosexuality</category><category>laptop</category><category>music</category><category>podcasting</category><category>subversion</category><category>virtualization</category><category>administration</category><category>birthday</category><category>caleb</category><category>command line</category><category>desktop</category><category>equality</category><category>gay</category><category>holiday</category><category>kernel</category><category>movie</category><category>opinions</category><category>packaging</category><category>phone</category><category>problem</category><category>rachel</category><category>school</category><category>super heroes</category><category>university</category><category>upgrade</category><category>virtual machine manager</category><category>RIchard Feynman</category><category>advice</category><category>advocacy</category><category>angular</category><category>apache</category><category>arm</category><category>artist</category><category>author</category><category>bash</category><category>biology</category><category>book</category><category>comedy</category><category>computer</category><category>convention</category><category>cooking</category><category>customer service</category><category>debugging</category><category>design pattern</category><category>emotion</category><category>encapsulation</category><category>essay</category><category>exercise</category><category>family</category><category>festival</category><category>free software</category><category>ftl</category><category>gnome</category><category>gripes</category><category>hacking</category><category>health</category><category>hiking</category><category>humor</category><category>java</category><category>javascript</category><category>kde</category><category>keyboard</category><category>macos</category><category>marriage</category><category>maven</category><category>messaging</category><category>mutt</category><category>news</category><category>online</category><category>open source</category><category>perl</category><category>philosophy</category><category>phishing</category><category>physics</category><category>politics</category><category>present</category><category>qpid</category><category>rails</category><category>rights</category><category>rpm</category><category>rumor</category><category>search</category><category>seasons</category><category>security</category><category>space</category><category>spring</category><category>spring boot</category><category>systemd</category><category>technology</category><category>television</category><category>test driven development</category><category>typescript</category><category>update</category><category>utility</category><category>video</category><category>virtualbox</category><category>weekend</category><category>work</category><category>zombies</category><title>Flaws In Progress</title><description>I write code for fun and profit. </description><link>http://mcpierce.blogspot.com/</link><managingEditor>noreply@blogger.com (mcpierce)</managingEditor><generator>Blogger</generator><openSearch:totalResults>107</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><language>en-us</language><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-3153187285241682574</guid><pubDate>Mon, 16 Mar 2020 13:58:00 +0000</pubDate><atom:updated>2020-03-16T09:59:03.986-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">advice</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Today's Piece Of Advice For Programmers</title><description>&lt;br /&gt;
&lt;div style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;
&lt;img alt="https://www.incimages.com/uploaded_files/image/970x450/Homer-Simpson_33041.jpg" height="185" src="https://www.incimages.com/uploaded_files/image/970x450/Homer-Simpson_33041.jpg" width="400" /&gt;&lt;/div&gt;
&lt;br /&gt;
If you're going to add a static method to a class that takes as input an instance of the class and some data to update the state of that instance, then why no &lt;b&gt;make it an instance method&lt;/b&gt;? That way, when someone needs to refactor the code, they won't sit and wonder why you did such a thing and question your abilities as a developer.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2020/03/todays-piece-of-advice-for-programmers.html</link><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-5465713819968975736</guid><pubDate>Thu, 09 Jan 2020 15:55:00 +0000</pubDate><atom:updated>2020-01-09T10:55:33.569-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">command line</category><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">maven</category><category domain="http://www.blogger.com/atom/ns#">programming</category><category domain="http://www.blogger.com/atom/ns#">spring</category><category domain="http://www.blogger.com/atom/ns#">spring boot</category><title>Maven And Spring Boot: Get Maven Plugin Command Line Options</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div style="margin-left: 1em; margin-right: 1em;"&gt;
&lt;div style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;
&lt;img alt="Spring Boot 2.0.0" class="attachment-large size-large" data-attachment-id="335" data-comments-opened="1" data-image-description="" data-image-meta="{&amp;quot;aperture&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;credit&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;camera&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;caption&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;created_timestamp&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;copyright&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;focal_length&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;iso&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;shutter_speed&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;title&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;orientation&amp;quot;:&amp;quot;0&amp;quot;}" data-image-title="spring-boot-logo" data-large-file="https://i2.wp.com/www.thecuriousdev.org/wp-content/uploads/2017/12/spring-boot-logo.png?fit=600%2C315&amp;amp;ssl=1" data-medium-file="https://i2.wp.com/www.thecuriousdev.org/wp-content/uploads/2017/12/spring-boot-logo.png?fit=140%2C74&amp;amp;ssl=1" data-orig-file="https://i2.wp.com/www.thecuriousdev.org/wp-content/uploads/2017/12/spring-boot-logo.png?fit=600%2C315&amp;amp;ssl=1" data-orig-size="600,315" data-permalink="https://www.thecuriousdev.org/new-in-spring-boot-2/spring-boot-logo/" height="105" src="https://i2.wp.com/www.thecuriousdev.org/wp-content/uploads/2017/12/spring-boot-logo.png?fit=600%2C315&amp;amp;ssl=1" width="200" /&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;/div&gt;
One of the issues I hit regularly is remembering the various command line arguments that can be sent to the Maven Spring Boot plugin. Specifically, arguments to be passed to the underlying application when I'm doing:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;&amp;nbsp;$ mvn spring-boot:run&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
To find the list of options, use the following command line:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;&amp;nbsp; $ mvn help:describe -Dcmd=spring-boot:run -Ddetail&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Which outputs the following:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;Mojo: 'spring-boot:run'&lt;br /&gt;spring-boot:run&lt;br /&gt;&amp;nbsp; Description: Run an executable archive application.&lt;br /&gt;&amp;nbsp; Implementation: org.springframework.boot.maven.RunMojo&lt;br /&gt;&amp;nbsp; Language: java&lt;br /&gt;&amp;nbsp; Bound to phase: validate&lt;br /&gt;&amp;nbsp; Before this goal executes, it will call:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Phase: 'test-compile'&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Available parameters:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; addResources (Default: false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.addResources&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add maven resources to the classpath directly, this allows live in-place&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; editing of resources. Duplicate resources are removed from target/classes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; to prevent them to appear twice if ClassLoader.getResources() is called.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Please consider adding spring-boot-devtools to your project instead as it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; provides this feature and many more.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; agent&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.agent&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Path to agent jar. NOTE: the use of agents means that processes will be&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; started by forking a new JVM.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.arguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Arguments that should be passed to the application. On command line use&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; commas to separate multiple arguments.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; classesDirectory (Default: ${project.build.outputDirectory})&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Required: true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Directory containing the classes and resource files that should be&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; packaged into the archive.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; environmentVariables&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List of Environment variables that should be associated with the forked&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; process used to run the application. NOTE: the use of Environment&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; variables means that processes will be started by forking a new JVM.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; excludeGroupIds&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.excludeGroupIds&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Comma separated list of groupId names to exclude (exact match).&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; excludes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.excludes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Collection of artifact definitions to exclude. The Exclude element&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defines a groupId and artifactId mandatory properties and an optional&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; classifier property.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; folders&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.folders&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Additional folders besides the classes directory that should be added to&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; the classpath.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fork&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.fork&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Flag to indicate if the run processes should be forked. fork is&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; automatically enabled if an agent, jvmArguments or working directory are&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; specified, or if devtools is present.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; includes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.includes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Collection of artifact definitions to include. The Include element&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defines a groupId and artifactId mandatory properties and an optional&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; classifier property.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; jvmArguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.jvmArguments&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JVM arguments that should be associated with the forked process used to&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; run the application. On command line, make sure to wrap multiple values&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; between quotes. NOTE: the use of JVM arguments means that processes will&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; be started by forking a new JVM.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mainClass&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.main-class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The name of the main class. If not specified the first compiled class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; found that contains a 'main' method will be used.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; noverify&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.noverify&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Flag to say that the agent requires -noverify.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; profiles&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.profiles&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The spring profiles to activate. Convenience shortcut of specifying the&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'spring.profiles.active' argument. On command line use commas to separate&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; multiple profiles.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; skip (Default: false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.skip&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Skip the execution.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; systemPropertyVariables&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List of JVM system properties to pass to the process. NOTE: the use of&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; system properties means that processes will be started by forking a new&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JVM.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; useTestClasspath (Default: false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.useTestClasspath&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Flag to include the test classpath when running.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; workingDirectory&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; User property: spring-boot.run.workingDirectory&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Current working directory to use for the application. If not specified,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; basedir will be used. NOTE: the use of working directory means that&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; processes will be started by forking a new JVM.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
And then, specifically, to provide arguments to the underlying application, you would use:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;&amp;nbsp; $ mvn spring-boot:run -Dspring-boot.run.arguments=[the list of comma separated options]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2020/01/maven-and-spring-boot-get-maven-plugin.html</link><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-3023162809726751622</guid><pubDate>Wed, 08 Jan 2020 16:39:00 +0000</pubDate><atom:updated>2020-01-08T11:51:37.365-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">angular</category><category domain="http://www.blogger.com/atom/ns#">design pattern</category><category domain="http://www.blogger.com/atom/ns#">encapsulation</category><category domain="http://www.blogger.com/atom/ns#">typescript</category><title>Angular, NgRx And Adaptors: Separating State From Observers</title><description>&lt;br /&gt;
&lt;div style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;
&lt;a href="https://www.blogger.com/blogger.g?blogID=2161762455502736718" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;/a&gt;&lt;img alt="Image result for adaptor&amp;quot;" class="n3VNCb" data-noaft="1" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUSEhMVFRUVFRUVFRUVFxUVFxYVFRUWFhUVFRcYHSggGBolGxUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OFxAQGi0lHR0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAMIBAwMBIgACEQEDEQH/xAAbAAADAQADAQAAAAAAAAAAAAAAAQIDBAUGB//EADcQAAIBAgMFBQkAAQQDAQAAAAABEQIhAzFBBFFhcYEFEpGx8AYTIjKhwdHh8UIUI2KicoKyB//EABkBAQEBAQEBAAAAAAAAAAAAAAABAgMEBf/EACkRAQEAAgEEAQEIAwAAAAAAAAABAhEDBBIxQSETIlFhcZGhsdEFFCP/2gAMAwEAAhEDEQA/APEItEopHN1UNCQwhooUDgqCBwNAADSCBwAQEDQBCQmUEFCQ4HA4IIgCoCChCgqAAiBFtCggQBA0FIUFCIJgGUJgQyWWyWBx8XCTODi7O0dozOtEs23jncXTOpgdhVgIDPZHb/YcmkpE0lpnR5zRaQqUCCKpGiJLQDQ+AIEVDgaEkCAYIBsIRSENAMQi6FLAliTLrpIAoIAAEKCmIBQEDEF2QDYQQQxMpiYNoZLKZLQEszqNGQwM2gGAFJFkU8SkyqtFUEJGn2CBDFSx6AUAPQYQJDgSGAQEAgbAaCRAEUxSJggKkGIdIDQMSBsBiCRgIIGJgTIwgUBSYmNksBMllEMCWQymTUBAAAFKw6fK5CevGDTh6uGlcCkSrDpQRSepapM0VOQRakCq8JqE9VOmTyJp3FRTElIJcchJAU0DQkwzApAJDCBoIB5AwBggYUhQ2UhAEAgGFIYgTAGgCQAVRDRVTJAO44kzZo63EEMCGZ1M0qM6gJkCYAaDoXgaPgRT+syl5BpfrpxLn1xIT87fgKXLy48wjSjd64hIkinKXqc9QhpFJeYkvXMqnl01CDJjVNzlYHZWLX/g+bilf9oOdhdgv/PES4Up1ecIlsjllz8ePmumXAIPTYPY2Cs1VX/5OF4Ux5nNwcGmn5KaaeKSnxzM3OPPl1uE8Tbyuz7FiVfLRU51hx45HIfZGMlPd5/FS34Jnp2282EE764Xrs/UjxdVN3MqM09BRoeu2nYacWzUt2TyfiZ0+zFGGm8auq3+KUW45t9DUznt3x63DW8vivKwPuuJhxvg9xg7Lg4b+HCpphNurEam3Ntzwsb4m12v8jcUuH8SS+JpNKymPElzjnf8hN/GL5+kI9bjdqOiru4eFSqE71OJdOtkcbavd4tKqapWJLnurSbPjJPqR1w6uWyWal9vNNjk76jszDqoqbqh27vHjuR0204Dobpemu8uHJMnvyw7fn0zqJBDZ0YIQ0Q2QMkcEtgEksuukzbAmSKimJgZsAACU5dukOb9C3GVp16mdVWk/qxpU8r/AH6ho0+H81Zqn5R05aEuEvxn1jISqWv7zgI0b/XreVR4Sye9aUpzvl480U05srcN2UeQTb0nsZ2JRtFVbxPlpjupNqanMTws/od1jbP7qp0qlUckl9c2Y+zWNTs+ye9xLKrEz6qhdLN+J6ba9nWNRK+ZKzWqM5z7vT4fUc9y5cp68PMyBWJTDhnH2itql92J0nI4ubeRpnGdcJTXS6taKaW2vBmlSrq+GhQ2m5qcRCvbMI3kJFseGqaGq6m6rQ+M3XIUgVJ2dO1rGw/d4j+NKKK9/wDxq3nUtkNllR1+3bZV3mqqqk1Zx3Z8WmcbF7RcRLie85bbbiJl8Ds8TZaam3Upb11PK7XNFdVDzTj8Mxdu/HjL+bm17WzB7QcF4xliY5HeYu62Xa3DSuY7ZXLu7nSV4mJVaib5vJHJ2PBdKcuW8zpx4Xe31OLP/jMa5XeExd4Fc9CGwaExSA2ibB3xIAqxLQZspkkCZBTIqYEgJsAuyT8occIzsPPTXPL6viRnCTd49fQtOLQso1nmVpqnad8Prk7zf+FUrm7TproZu+uebLodnGeu++UeH1CNE93XdP8AWObatRL3uqIuSkp++uiVupeGoq+J6rvW0nT1qiyfLFr1ntV/t7Hs+DrFLq5qmX/2qNvYfth0004WJVr/ALbb/wCv4J9t9jqxlhYuG5o7ruslN0+TXkcCn2RxHsVW04GI3Xh1f7mHrTSkmq6dWpbn9ExlvdfxfJ6fix58LL5t/d7btjYe+veUK/8AkvuebxsBVWqUw5O59kO0sXFwFVi0tNN0VVNRTW1Ztcd/EfbHZ/d+On5X9Dlnjp5ftY245eY6jHXeUU/Bl8tpjfvHSknKmYiW5fGNwmBzVUgIzxMemm7aQRqI6ja/aDCoycnRbb7UV1WpsHXHhzy8R7DG2iii9VSR5D2h22iutVUbofQ6TH26uvOpnAxtrScZlmNr18PTWXbsatoM3W6tTq3tLfA3wK2bmGnuw4Z7d1hYiShdTdY0nV4dZtTUa27dsdhTiFLEOAq7miqHcdrlrERUnD7w1iF2mnJbBswVYnWXaabMlslVg6ioGQyiGwFACYBUUvhOVtOpVKbtKXTdrJFGm5Xy+oU35xIVvRnLem7+aFN2hcJ56Myplu8Q856mlojhutkwiklGSt136cjSlO0Kd/DwUZGWDbNxx1T8L5jahRxfXP6Irnl4ev8AY/tbPZsVzTVPu50bzonc81x5o9P2XtNWyY0q9FVmtKqN3M+VYeJOvFRvUO2uh9E7B7TW1YXcqti0RPFaVrnrxNb1d/q+Tyy8HJ9SeL5/tye0tgdWNVibJ3lQ6qaqKW3HesqmqVa9le8Qd1gYk97DriVapTMOJI7BxaFX7vG+WpOnOIbyqn1mRV2X/p8WulpuVNNc2a5b/XPOeM9eHbqcceXi+r7x/h0vbGzLBct20Z57a+3cOjWTD/8ARe1261hUv5Vc8LXW3mebTj0/D34zKvS7Z7UVP5bHS7R2lXXm2cKQHbHsx4ccfEU6pFIpFVWlmadZBi1wpOvSN8avvchU0G8Zp3wx1Cw6Dk4VIqMM3oQrrF0GtFRFJUEVoqizNZDVXiBaKdRLYmEV3hqqTN8gyCNe+U6jFMvvGolX3xNkTuBs0ypgZyIATyU5ItO0vXThvMqmtJlS+ZUWW5fcNNVf6ekaJqHz9PzMk/TGrwrZNfsI1luJ03fcfdnOyznnouJnGU8r8NSo1z9btcisVpQrpvLhZnL7P2yrBrpxMPOnfqrTS+DRwe9a8+Xh9DVK2asnxmXkaefk45lNV9P2faKdowqcbD1V1qozpfFHb4naVVWz0quH3Jip5wlk/Wh8x9me2f8AT4l3/t1/OlpGVVK4a8D1/tX2mqNmqrTT7y+FrJp6oxn9mWTw+PyTPj3xTxl4fK/aDaveY9dX/JnWjxK82zj17StL+RxkfZ4+PWMk9N5M8TGSzZxasRvWOQqaDUxd5x/e1e0N5WM1TLl35lU0G1NO814dJjJ4TTSbU0gkaJeRGtCinQ1Qqf5+BpEFeuhSJWRQVSzHJDHO8IqbDnoQwbAtVA2T3hAVI+8SM0ytvQVTFUJGkDGKQCIbNEvhy9IxeRpTuYarTvKI4l0067sjDvcDV07npcqVpRUtd1lpzZTTt9FlHAiiG+Wu+AdefHJhlaryTn7TvNI8He346ENw98XeQnTN4jXoVixr3psuMebRh2l2hi1YdOCqvgV6U7xwT3Fe84TZHGxFndStNOIvy5fTlu7HT4uzVa3I9y1mjtHhrPJX8SVT68idr0zJ1qpKVJz/AHFlu18xe59RyJprbiU07+iNUcj3St/AeEZ0u2SL7pao9Z/TUO4RdlzAfc8xxeJ8PKegDpf4HTy/vqReHrmF3Ph9/XIAny8yqU/pPQVOeebCNcvAgbeQOoJjy6CX1KDwGhSNhDneNOwo5R5jbNRkNC4jmfVxFFSBmBUQqsilSZ2kupkaaTkUneSFD1BO+ZUbJvKYKpcy3oZSV3rwvXAI0T8rluqEuPEwpqjkXS/FZlSqqcXy+pkqozzCqvrew3L+bJbgmmUWtfOSm7TCvplyNaKmpVOTV+RniekFTG7LdkCptdW35lOmXbkwStOX3vuAKVGfTiLuXvF3ncp3h5Wv+ysJ5t5ZeuAXaHRz3c/W8lUx5f3oaV3eWtlkCSm8/ozo2ipZz6chOuV+saXRT/K06/0Ufj6fwaXafd/f8SFVOnrxLpWTzdt/V8RUpN5dJ+zz/RNG0vwUT1WpNp19alNvj+ov0HTv4dc49chpdoqS1f8AN449cfXmU8uGf0uuYm9Iy8vXkNJtPpfwHbL6/ccdNObFMc/W8aNjTQa9cxTbOAfH14lTZz+yamCq9IVNUP8AhQmxABURQNuxnTUXJltaZUkd7eUnYqLorgpNZ8czGlosDT7lUNaPSDNKw3bmEN7tw4zmxnh7y5n7IB0Kq7U8S+9bRszfDUO/3QKor11yY6UpWWVye9MyWn6RURTVfy3dR0riKZu9d30K3J6fQim67wl1vmKd+adtwm468fqxqb5acAgTv5zbqDjc4mLRcXeu9/D8jncuugCyyi24ULj+mr3Kbu/qt/QE1z3TonzAnLPS3jr63kR0VrodV8o5FOdN2mULNMip3eXPf61FTTOXHh0+hayW7W/T0iZe5S+tgJfS0fj1oLguo1u458gpeb9cwCpv8PK3pktaZcB0OLcvAnrN+hQ56acyWv1cKunrUmfu55Z+YCbAhrj5gUSikAGWzLwgArNOkazAALo1Kws+gAAqAoy6gAg0IpzAAHV9jWhfEuQAETF+hLfxeAAAavmjSnTmwAFTtHzPqLRc0ACDTDv3p3r7mTXrwGAvlDqV6ua/+WFWVQAWKzo9fQqtW8fMYE9owpfrxYUvLk/sABSpZLd1/wCowAl5eHmOn7/gACsqswACK//Z" style="margin: 0px;" /&gt;&lt;/div&gt;
&lt;br /&gt;
In this post I'm going to discuss a model we've developed on my &lt;a href="https://github.com/comixed/comixed" target="_blank"&gt;open source project&lt;/a&gt; as well as in my day job. With it we hide the details for state management in an Angular application that is using NgRx &lt;a href="https://ngrx.io/guide/store" target="_blank"&gt;stores&lt;/a&gt; and &lt;a href="https://ngrx.io/guide/effects" target="_blank"&gt;effects&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Overview&lt;/h2&gt;
When working with NgRx, one of the issues to solve is to provide state management without too tightly coupling the details of that state with the components that benefit from it. You want to avoid having your components reacting to every change in that state when the changes are of no interest to that component's area of concern. For example, if your application has a state for managing the currently authenticated user, you may not want your navigation bar have to process a state update at any time other than when the user's name or email address is changed or if their authentication state changes.&lt;br /&gt;
&lt;br /&gt;
The goal of this pattern is to hide the details of that state management inside of an injectable class that maintains knowledge of that state, provides methods to initiate actions and observables to allow components to subscribe to only specific changes in state, those in which it is interested.&lt;br /&gt;
&lt;br /&gt;
In our example project, we've created a simple feature to perform multiplication and division. It provides the simple ability to multiply two numbers and return the product of those them. To accomplish this we provide the actions, the reducer and the effects to perform this operation. And to hide the details, we provide an adaptor that can be injected into any component to allow it to either initiate this behavior, to receive updates when such behavior concerns, or to do both.&lt;br /&gt;
&lt;h2&gt;
The Adaptor Details&lt;/h2&gt;
Our adaptor code is very simple:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;@Injectable()&lt;br /&gt;export class MultiplicationAdaptor {&lt;br /&gt;&amp;nbsp; private _first$ = new BehaviorSubject&amp;lt;number&amp;gt;(0);&lt;br /&gt;&amp;nbsp; private _second$ = new BehaviorSubject&amp;lt;number&amp;gt;(0);&lt;br /&gt;&amp;nbsp; private _product$ = new BehaviorSubject&amp;lt;number&amp;gt;(0);&lt;br /&gt;&amp;nbsp; private _showProduct$ = new BehaviorSubject&amp;lt;boolean&amp;gt;(false);&lt;br /&gt;&lt;br /&gt;&amp;nbsp; constructor(private store: Store&amp;lt;AppState&amp;gt;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.store&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .select(multiplierFeatureKey)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .pipe(filter(state =&amp;gt; !!state))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .subscribe((state: MultiplicationState) =&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('*** state:', state);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this._first$.getValue() !== state.first) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._first$.next(state.first);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this._second$.getValue() !== state.second) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._second$.next(state.second);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this._product$.getValue() !== state.product) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._product$.next(state.product);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this._showProduct$.getValue() !== state.showProduct) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._showProduct$.next(state.showProduct);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; get first$(): Observable&amp;lt;number&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._first$.asObservable();&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; get second$(): Observable&amp;lt;number&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._second$.asObservable();&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; get product$(): Observable&amp;lt;number&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._product$.asObservable();&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; get showProduct$(): Observable&amp;lt;boolean&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this._showProduct$.asObservable();&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; evaluate(first: number, second: number, online: boolean): void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.store.dispatch(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new MultiplierEvaluate({ first: first, second: second, online: online })&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the adaptor is very simple. When created it is give a reference to the NgRx store and subscribes itself to state changes, and then updates a set of BehaviorSubject instance variables based on changes to the state.&lt;br /&gt;
&lt;br /&gt;
A key piece of efficiency here is in how the adaptor updates those subjects each time the state changes: it only updates those that have changed since the last update. So, for example, if the first value wasn't changed by the user, then no update is published when the next state change occurs.&lt;br /&gt;
&lt;br /&gt;
This adaptor is then injected into any component that is interested in receiving updates.&lt;br /&gt;
&lt;br /&gt;
In our example application, &lt;a href="https://github.com/mcpierce/blogging-code/blob/master/ngrx-adaptor-pattern/src/app/app.component.ts" target="_blank"&gt;AppComponent&lt;/a&gt; is the type that subscribes only to notifications to show the product and the values involved, while the &lt;a href="https://github.com/mcpierce/blogging-code/blob/master/ngrx-adaptor-pattern/src/app/multiplication/multiplication.component.ts" target="_blank"&gt;MultiplicationComponent&lt;/a&gt; is the type that initiates the process based on user interactions.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaHfCC9_5ZSOtNQKy4mH2HhG_P62ow__T0Pq8kfYLm1BvVWgpwaTqF78yw1M74g3EVcSmsl6iHrIAWh87rkW2zEokI3wnjQAzB7IpJ76Pk7Ixh3Ak0on4E2KAO807RiLknGt_W6o4KLJc/s1600/Screen+Shot+2020-01-08+at+11.08.35+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaHfCC9_5ZSOtNQKy4mH2HhG_P62ow__T0Pq8kfYLm1BvVWgpwaTqF78yw1M74g3EVcSmsl6iHrIAWh87rkW2zEokI3wnjQAzB7IpJ76Pk7Ixh3Ak0on4E2KAO807RiLknGt_W6o4KLJc/s640/Screen+Shot+2020-01-08+at+11.08.35+AM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;
Initiating Actions&lt;/h2&gt;
To start the process, the user enters the first and second values into the form and clicks the &lt;b&gt;Evaluate&lt;/b&gt; button. This results in the following call to the adaptor:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;this.multiplicationAdaptor.evaluate(&lt;br /&gt;&amp;nbsp; this.multiplicationForm.controls.first.value,&lt;br /&gt;&amp;nbsp; this.multiplicationForm.controls.second.value&lt;br /&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This passed the two values to the adaptor, which then translates that into NgRx action that is dispatched for processing. Below is the code from the adaptor:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;evaluate(first: number, second: number): void {&lt;br /&gt;&amp;nbsp; this.store.dispatch(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new MultiplierEvaluate({ first: first, second: second })&lt;br /&gt;&amp;nbsp; );&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
With this we have decoupled our component from how the action is performed.&lt;br /&gt;
&lt;h2&gt;
Observing State Changes&lt;/h2&gt;
When the state changes, there are four things potentially published to observers: changes to the first and second values, changes to the product, and changes to the flag to show or hide the product.&lt;br /&gt;
&lt;br /&gt;
Our application component is provide an instance of our adaptor (code not shown for brevity). In its Typescript code the component subscribes to updates to the show product flag and then sets its own local instance variable based on changes to the state:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;ngOnInit(): void {&lt;br /&gt;&amp;nbsp; this.multiplicationAdaptor.showProduct$.subscribe(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; show =&amp;gt; (this.showProduct = show)&lt;br /&gt;&amp;nbsp; );&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This flag toggles showing or hiding the multiplication output as we see below:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;&amp;lt;div *ngIf='showProduct'&amp;gt;
  &amp;lt;h2&amp;gt;Multiplication Output&amp;lt;/h2&amp;gt;
  The product of {{multiplicationAdaptor.first$|async}}&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;            &amp;nbsp;and {{multiplicationAdaptor.second$|async}}&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;"&gt;              is {{multiplicationAdaptor.product$|async}}.
&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
A key piece to take note of in the HTML is how the values and the product are updated in the HTML. Rather than storing these values as instance variables on the component, the adaptor is accessed directly and, since it's an Observable, is filtered through Angular's &lt;a href="https://angular.io/api/common/AsyncPipe" target="_blank"&gt;AsynPipe&lt;/a&gt;. The further reduces the amount of code needed to translate state changes to updates for the user.&lt;br /&gt;
&lt;h2&gt;
So, What Are The Benefits?&lt;/h2&gt;
As you can see from this simple example, the benefits are a separation of concerns between the various components in the application and the processing of state changes, and of publishing those changes atomically to components that are interested in specific changes to the state.&lt;br /&gt;
&lt;h2&gt;
Source Code&lt;/h2&gt;
You can view the source code for this project &lt;a href="https://github.com/mcpierce/blogging-code/tree/master/ngrx-adaptor-pattern" target="_blank"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
As with any other code, if you find any errors of have an update to share, please send them over and I'll include them. </description><link>http://mcpierce.blogspot.com/2020/01/angular-ngrx-and-adaptors-separating.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaHfCC9_5ZSOtNQKy4mH2HhG_P62ow__T0Pq8kfYLm1BvVWgpwaTqF78yw1M74g3EVcSmsl6iHrIAWh87rkW2zEokI3wnjQAzB7IpJ76Pk7Ixh3Ak0on4E2KAO807RiLknGt_W6o4KLJc/s72-c/Screen+Shot+2020-01-08+at+11.08.35+AM.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-8836781942539545952</guid><pubDate>Tue, 14 Nov 2017 20:41:00 +0000</pubDate><atom:updated>2017-11-14T15:41:48.280-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">macos</category><category domain="http://www.blogger.com/atom/ns#">virtualbox</category><category domain="http://www.blogger.com/atom/ns#">virtualization</category><title>Fedora VM Flickering? Here's A Fix!</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij9uL1aH5E9BoNao_gmSTt4EMESLfSqds9uNLa3LPlPJxihJdcrkzYdrs0KElym3rMIvb82E1XGUa2MLBgahA25Qz72x80df69cLRds5zHx49NNHGXp9Byy8lBae8Kla1UrQAOmwAXakw/s1600/Virtualbox_logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="512" data-original-width="512" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij9uL1aH5E9BoNao_gmSTt4EMESLfSqds9uNLa3LPlPJxihJdcrkzYdrs0KElym3rMIvb82E1XGUa2MLBgahA25Qz72x80df69cLRds5zHx49NNHGXp9Byy8lBae8Kla1UrQAOmwAXakw/s200/Virtualbox_logo.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
Today I installed &lt;a href="https://www.virtualbox.org/" target="_blank"&gt;VirtualBox&lt;/a&gt; on my MacBook Pro so that I could run a virtual instance of &lt;a href="https://getfedora.org/" target="_blank"&gt;Fedora 27&lt;/a&gt;. After the install finished, though, I found that the guest screen was repeatedly flickering. Not sure what the problem was, I started googling and found a forum that pointed me to &lt;a href="https://wayland.freedesktop.org/" target="_blank"&gt;Wayland&lt;/a&gt; as the culprit.&lt;br /&gt;
&lt;br /&gt;
I logged out of Gnome, logged back in but first selected the settings gear and told GDM I wanted "Gnome on Xorg". Once I was logged in the flicker was gone.&lt;br /&gt;
&lt;br /&gt;
I'm not entirely sure what the problem is, but at least at this point it's working.</description><link>http://mcpierce.blogspot.com/2017/11/fedora-vm-flickering-heres-fix.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij9uL1aH5E9BoNao_gmSTt4EMESLfSqds9uNLa3LPlPJxihJdcrkzYdrs0KElym3rMIvb82E1XGUa2MLBgahA25Qz72x80df69cLRds5zHx49NNHGXp9Byy8lBae8Kla1UrQAOmwAXakw/s72-c/Virtualbox_logo.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-7033558814256711932</guid><pubDate>Wed, 15 Jul 2015 14:11:00 +0000</pubDate><atom:updated>2015-07-15T10:11:34.094-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Installing NVM And Node.js To Your Home Directory</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivSLT3W68p1pLFf1MMTn7sGGnIVzkZmtE0O1wCBCfR6rap3twUgXnjLbt6Uei0j82wHqzJcrs0tNB0WKmDnm_uzoKOh3Hgq6jH7yBqILp8iImXbzgru5qNxO49V5_IpOsGlee7O5uo3lQ/s1600/nodejs-light.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivSLT3W68p1pLFf1MMTn7sGGnIVzkZmtE0O1wCBCfR6rap3twUgXnjLbt6Uei0j82wHqzJcrs0tNB0WKmDnm_uzoKOh3Hgq6jH7yBqILp8iImXbzgru5qNxO49V5_IpOsGlee7O5uo3lQ/s1600/nodejs-light.png" /&gt;&lt;/a&gt;&lt;/div&gt;
On Fedora I've found that installing node.js and npm to be less than useful for my needs; i.e., while they install and work, they want to put things into the system directories and not my home directories. And, like with Ruby on Rails, you get locked into whatever is the latest version packaged for Fedora itself, which isn't always what you'd want.&lt;br /&gt;
&lt;br /&gt;
What would be nice is to have something akin to RVM for Ruby, that lets you install the specific version you want regardless of what's packages for your release.&lt;br /&gt;
&lt;br /&gt;
Enter &lt;a href="https://github.com/creationix/nvm" target="_blank"&gt;NVM&lt;/a&gt;, the Node Version Manager. The name is even reminiscent of RVM! :D&lt;br /&gt;
&lt;br /&gt;
To install this on my Fedora system, I first downloaded the nvm release script and executed it using:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.12.1/install.sh | bash&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and then sourced my .bash_profile, which was updated to include NVM.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;$ . ~/.bash_profile&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
I then checked to see what the latest version of node.js was to download and install&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;$ nvm current&lt;br /&gt;v0.12.7&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
so I could be sure to install the latest version, which I did:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;$ nvm install v0.12.7&lt;br /&gt;######################################################################## 100.0%&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Then, to use it, you type:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;$ nvm use v0.12.7&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and you should now see node in your path:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; $ which node&lt;br /&gt;~/.nvm/v0.12.7/bin/node&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2015/07/installing-nvm-and-nodejs-to-your-home.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivSLT3W68p1pLFf1MMTn7sGGnIVzkZmtE0O1wCBCfR6rap3twUgXnjLbt6Uei0j82wHqzJcrs0tNB0WKmDnm_uzoKOh3Hgq6jH7yBqILp8iImXbzgru5qNxO49V5_IpOsGlee7O5uo3lQ/s72-c/nodejs-light.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-5439654447404525968</guid><pubDate>Wed, 01 Jul 2015 21:49:00 +0000</pubDate><atom:updated>2015-07-01T17:49:50.668-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">virtual machine manager</category><title>Converting VMWare Disk Images For Use With QEMU</title><description>At my current job we have a VM that was created by someone using VMware which hosts a scaled down version of our runtime environment. Being the new guy, and someone who's way more comfortable with Fedora Linux than Windows, I wanted to take the VM and run it on my favorite OS.&lt;br /&gt;
&lt;br /&gt;
But I couldn't just copy the image over since the 60G disk was split up into 31 separate VMDK files, which cried out to be converted to a format usable by Linux.&lt;br /&gt;
&lt;br /&gt;
So here's what I did:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp;$ for vmdk in *.vmdk; do qemu-convert -f $vmdk -O raw $(basename -s .vmdk $vmdk).img; done&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp;$ cat *.img &amp;gt;&amp;gt; runtime_environment_vm.img&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When it was all done I had a bootable disk. I created a new VM using that disk and was off to work in no time!&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9htE76ygXxOostkN1PnCyn1u6uB_P8RjZHZgpfrSyxbiRSgJ37sNet7v_SR19ChTskveqEww84f3hgtvv8-THUK60BB2YNtSksHptplRtuFeUzRuRy8W8IOi0n7SF1RXRnh0MmSrnl4Q/s1600/libvirt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9htE76ygXxOostkN1PnCyn1u6uB_P8RjZHZgpfrSyxbiRSgJ37sNet7v_SR19ChTskveqEww84f3hgtvv8-THUK60BB2YNtSksHptplRtuFeUzRuRy8W8IOi0n7SF1RXRnh0MmSrnl4Q/s640/libvirt.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2015/07/converting-vmware-disk-images-for-use.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9htE76ygXxOostkN1PnCyn1u6uB_P8RjZHZgpfrSyxbiRSgJ37sNet7v_SR19ChTskveqEww84f3hgtvv8-THUK60BB2YNtSksHptplRtuFeUzRuRy8W8IOi0n7SF1RXRnh0MmSrnl4Q/s72-c/libvirt.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-2780463096887866989</guid><pubDate>Wed, 03 Jun 2015 12:55:00 +0000</pubDate><atom:updated>2015-06-03T08:55:34.129-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">git</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>More Git Commit Recovery With RefLog</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPPpSWK4WisiNQbgbuTmqksBR1oI2eryo1eIvm4O4yBolIagnafcnJ7YTWibnHB5t24l2YTdosu4W4LM6hldo56ICcWXF8MHwqzwVD5d0UxN8u3SIGLA7QAvboQhNwHnCfGIFceSBOPbU/s1600/Git-Logo-Black.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPPpSWK4WisiNQbgbuTmqksBR1oI2eryo1eIvm4O4yBolIagnafcnJ7YTWibnHB5t24l2YTdosu4W4LM6hldo56ICcWXF8MHwqzwVD5d0UxN8u3SIGLA7QAvboQhNwHnCfGIFceSBOPbU/s400/Git-Logo-Black.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
Yesterday I blogged about &lt;a href="http://mcpierce.blogspot.com/2015/06/recovering-lost-commit-with-git.html" target="_blank"&gt;how I lost and then recovered a few commits&lt;/a&gt; in a small project I'm working on using git's cherry-pick command. Till Maas pionted out on G+ that you can get a list of the commits in your git repo with "git reflog".&lt;br /&gt;
&lt;br /&gt;
The reflog command (for reference log in case the contraction was lost in you) lets you look back into the repository history beyond what makes up its current state. In our case, it can show past commit hashes so we can find and recover a commit. This would have come in handy had I not had the output of a &lt;b&gt;git log&lt;/b&gt; in my terminal yesterday.&lt;br /&gt;
&lt;br /&gt;
So, for example, I could look back through the history of my project to find all of my previous commits with:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp;$ git reflog show &amp;nbsp;| grep commit&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;b3c1cf2 HEAD@{0}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;1fc7d5a HEAD@{1}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;f8df984 HEAD@{2}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;801787d HEAD@{9}: commit (amend): fixup! Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;c23dde8 HEAD@{10}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;d16b829 HEAD@{18}: commit (amend): Got a basic running application.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;c49a3cb HEAD@{19}: commit: Got a basic running application.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;f43fe07 HEAD@{25}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;f02d3bd HEAD@{26}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;92a16aa HEAD@{30}: commit (amend): fixup! Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;4c8b148 HEAD@{31}: commit: fixup! Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;5db5426 HEAD@{32}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;11a6b02 HEAD@{33}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;df9f92e HEAD@{34}: commit (amend): Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;3deafab HEAD@{35}: commit: Added a Glade described main window.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;6330fe5 HEAD@{36}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;a5eda9c HEAD@{37}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;fcb58eb HEAD@{38}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;2a0d994 HEAD@{39}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;32b8ea8 HEAD@{40}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;165ae57 HEAD@{41}: commit (amend): Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;33f9885 HEAD@{42}: commit: Created the initial application shell.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;5ea907a HEAD@{43}: commit: Created an initial to-do list of tasks for the project.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;40a2f7a HEAD@{44}: commit (amend): Updated the README file with a little more details.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;7d32cb2 HEAD@{45}: commit (amend): Updated the README file with a little more details.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;53984e2 HEAD@{46}: commit (amend): Updated the README file with a little more details.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;360ea5c HEAD@{47}: commit (amend): Updated the README file with a little more details.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
And from this list I would have been able to find the commit(s) I wanted to recover using &lt;b&gt;git show&lt;/b&gt;&amp;nbsp;and then cherry-picked the appropriate one once found.&lt;br /&gt;
&lt;br /&gt;
Thanks Till!</description><link>http://mcpierce.blogspot.com/2015/06/more-git-commit-recovery-with-reflog.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPPpSWK4WisiNQbgbuTmqksBR1oI2eryo1eIvm4O4yBolIagnafcnJ7YTWibnHB5t24l2YTdosu4W4LM6hldo56ICcWXF8MHwqzwVD5d0UxN8u3SIGLA7QAvboQhNwHnCfGIFceSBOPbU/s72-c/Git-Logo-Black.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-8460022870701800834</guid><pubDate>Tue, 02 Jun 2015 18:14:00 +0000</pubDate><atom:updated>2015-06-02T14:14:36.369-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">git</category><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Recovering A Lost Commit With Git</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtvnFMWmQ8GSHkJElHqh9snLH6a9r1rY6yhAy6LJy5m2icSEDdFRI_4y7vVVxsj8p9veGlBKtguByP5T_01mhIbUWQ5kv7MpbD8hR6M2ARCTVyIjDF917U5BI_FQOSmgRvUedE6UWcdO4/s1600/Git-Logo-Black.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtvnFMWmQ8GSHkJElHqh9snLH6a9r1rY6yhAy6LJy5m2icSEDdFRI_4y7vVVxsj8p9veGlBKtguByP5T_01mhIbUWQ5kv7MpbD8hR6M2ARCTVyIjDF917U5BI_FQOSmgRvUedE6UWcdO4/s400/Git-Logo-Black.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Ever have one of those days where you make a bad decision?&lt;br /&gt;
&lt;br /&gt;
No, I mean with writing code.&lt;br /&gt;
&lt;br /&gt;
You do?&lt;br /&gt;
&lt;br /&gt;
How about with source control? Things like deleting a commit on your work branch and then realizing you didn't mean to delete it?&lt;br /&gt;
&lt;br /&gt;
Well, guess what? You're in luck! Git doesn't throw away your commits! And if, like me, you've accidentally.....okay, INTENTIONALLY deleted some work and then realized you want to recover it, you can!&lt;br /&gt;
&lt;br /&gt;
A little background: I'm playing around with a tool to let me create and post a series of entries on the blog for my comic book podcast (&lt;a href="http://www.comicbookupdate.com/" target="_blank"&gt;The Comic Book Update&lt;/a&gt;). What I do now is manually schedule hourly posts of comic previews when the publishers send them to me. Which results in about two hours throughout the week (usually while drinking coffee and watching the news) of creating 60 posts (10 posts per day) and setting the scheduled time.&lt;br /&gt;
&lt;br /&gt;
Tedious, I know. So I want to create a tool to do this.&lt;br /&gt;
&lt;br /&gt;
Long story short, I started playing with a Ruby solution, a Python and a Java solution. But after deleting Ruby, I realized I in fact DO want to use it. And it was the one I had explored the most, but dammit I already deleted it!&lt;br /&gt;
&lt;br /&gt;
Except, in my terminal buffer, I could still get to the commit hashes for the Ruby version!&lt;br /&gt;
&lt;br /&gt;
So what I did was checkout a clean branch in my project repo. I then scrolled up and, one by one, did a git cherry pick of each of those hashes.&lt;br /&gt;
&lt;br /&gt;
Voila! Commits were recovered!&lt;br /&gt;
&lt;br /&gt;
The reason why is that, even when you delete a commit with "git reset --hard HEAD~1" or doing an interactive rebase and deleting commits from the list to be included, git does NOT actually throw the commit away. Instead it leaves it in the set of objects in your .git directory until such a time as you do garbage collection.&lt;br /&gt;
&lt;br /&gt;
If you go into a repo and peek in the .git/objects directory you'll see a series of directories name 00, 01, ..., fe and ff (or some subset of them). Each of those is composed of multiple files, each representing a different commit. The parent directory is from the first two characters of the commit hash, and the filename is from the remainder of the hash. So if your hash id was &lt;b&gt;f43fe07d9df08fdb6440c562639eb4ad4ce4c49e&lt;/b&gt; then you'll find that specific commit itself in&amp;nbsp;&lt;b&gt;.git/objects/f4/3fe07d9df08fdb6440c562639eb4ad4ce4c49e&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Such a nice turn of luck not having to rewrite that initial bit of code....thank you git!</description><link>http://mcpierce.blogspot.com/2015/06/recovering-lost-commit-with-git.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtvnFMWmQ8GSHkJElHqh9snLH6a9r1rY6yhAy6LJy5m2icSEDdFRI_4y7vVVxsj8p9veGlBKtguByP5T_01mhIbUWQ5kv7MpbD8hR6M2ARCTVyIjDF917U5BI_FQOSmgRvUedE6UWcdO4/s72-c/Git-Logo-Black.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-3556382561149248211</guid><pubDate>Mon, 01 Jun 2015 13:19:00 +0000</pubDate><atom:updated>2015-06-01T09:19:39.482-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">configuration</category><category domain="http://www.blogger.com/atom/ns#">desktop</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><title>Finding That Sweet Spot: Focus On Guake</title><description>One of the things I do quite often is go to a terminal, do some short command or two, then close the terminal. I do this away from my coding terminal as I don't want to contaminate bash history with those commands, mainly because I do a lot of repetitive things &lt;b&gt;[1]&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
The application I use for such things is &lt;a href="https://github.com/Guake/guake" target="_blank"&gt;Guake&lt;/a&gt;, a great little popup terminal application that gives me exactly what I need: a simple terminal that I can show and hide without having to launch a new app. It's available on pretty much all Linux distros, so I don't think I need to tell you how to get it on your system.&lt;br /&gt;
&lt;br /&gt;
The way I have Guake configured is to popup up as a small window (50% width, 50% height) at the center bottom of my current display (on my two-monitor desktop it follows the mouse pointer).&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcl3WzqDfu5rsQ-LlCzGimJA2QLs8vDoIAOwfkdlQlQTFVOmttAzzogy619__gSjXifVpUoWo_x6_kkBcMdeYUeOhDdq85_1gPIvJvc2GXhCp1qFLY9KEFKfojJi6W4NBvK_d6FuazxLI/s1600/Screenshot+from+2015-06-01+09-03-28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcl3WzqDfu5rsQ-LlCzGimJA2QLs8vDoIAOwfkdlQlQTFVOmttAzzogy619__gSjXifVpUoWo_x6_kkBcMdeYUeOhDdq85_1gPIvJvc2GXhCp1qFLY9KEFKfojJi6W4NBvK_d6FuazxLI/s640/Screenshot+from+2015-06-01+09-03-28.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I like to have my desktop be visually appealing since I spend so much time in front of it, so I've played with various colors, layouts, etc. to get things just right. And for me, what I have now works well.&lt;br /&gt;
&lt;br /&gt;
Placement shows the terminal the currently active desktop (the one where my mouse is at the time), and it pops up on top and stays on top of any other application. I have the transparency of the window set to about 15% or so to allow me to see through the window: this way I can read something on my browser or editor, for example, without having to close and re-open Guake.&lt;br /&gt;
&lt;br /&gt;
To open Guake, I have &lt;b&gt;F12&lt;/b&gt; as my hotkey, with &lt;b&gt;F11&lt;/b&gt; to make it full screen. These are the default and they make perfect sense to me. Though, on my keyboards when I'm docked, &lt;b&gt;F12&lt;/b&gt; and &lt;b&gt;Print Screen&lt;/b&gt; are close enough together that I will hit the latter at least once per day by mistake. So every weekend it seems I'm deleting a half dozen screen shots.... :D&lt;br /&gt;
&lt;br /&gt;
The color scheme I chose is called "Hipster Green" (yeah, I hate that name too). For me I find the monochrome-like colors more visually appealing, not to mention less harsh on the eyes if I'm on my laptop in a dimly lit room &lt;b&gt;[2]&lt;/b&gt;. I use auto-colors in ls and the monochrome color scheme fits well with it.&lt;br /&gt;
&lt;br /&gt;
The option I go back and forth on is showing the tab bar. On the one hand I like to be able to quickly jump to a tab I want if it's open. But on the other hand I don't normally have more than two or three open at a time. So I hate sacrificing even that small bit of real estate. So it depends on how I'm feeling at any point whether it's enabled or not.&lt;br /&gt;
&lt;br /&gt;
To open URLs that appear in the window, I've checked the &lt;i&gt;Enable Quick Open when Ctrl+clicking on a filename in the terminal&lt;/i&gt;&amp;nbsp;option (verbose, right?) on the &lt;b&gt;Quick Open&lt;/b&gt; tab.&lt;br /&gt;
&lt;br /&gt;
All in all, Guake is a great, useful tool for me to perform quick tasks from a command line without having to either pollute my primary command history with trivial little things. All in a tool that is easily launched, used, and dismissed quickly.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[1]&lt;/b&gt; - I will, for example, have the following three commands in my coding terminal's history:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; $ git clean -xfd &amp;amp;&amp;amp; cmake all&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp; $ [run some test script, example app or other]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
My main workflow in those cases it to build the world, run whatever I'm working on, then scroll through the output and fix things in my editor. Then I go back to the coding terminal and hit &lt;b&gt;Up Up Enter&lt;/b&gt;, wait a second, then &lt;b&gt;Up Up Enter&lt;/b&gt; again.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[2]&lt;/b&gt; - I &lt;b&gt;LOVE&lt;/b&gt; to write code during a rain storm. Some of my favorite times have been to sit on the couch in my office at home while it's pouring rain out and work on code to the soothing sounds of rainfall.</description><link>http://mcpierce.blogspot.com/2015/06/finding-that-sweet-spot-focus-on-guake.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcl3WzqDfu5rsQ-LlCzGimJA2QLs8vDoIAOwfkdlQlQTFVOmttAzzogy619__gSjXifVpUoWo_x6_kkBcMdeYUeOhDdq85_1gPIvJvc2GXhCp1qFLY9KEFKfojJi6W4NBvK_d6FuazxLI/s72-c/Screenshot+from+2015-06-01+09-03-28.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-358829648096952748</guid><pubDate>Fri, 29 May 2015 18:33:00 +0000</pubDate><atom:updated>2015-05-29T14:33:56.571-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">upgrade</category><title>Upgrading Fedora From F21 To F22 With FedUp</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW1s20BFRkgSevcCaFd9v3LsrPUcccMWSiC-a4K9vVqxSaZLJZjE0ICpYp9jvhHlHtPYKDZlfBEZWRj9pDifWQAwPQGeU-72auVYDA6x_yYv5bcwawTGEs5uEOw1QZOk1TyQ5kIn-NC7A/s1600/Logo_fedoralogo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW1s20BFRkgSevcCaFd9v3LsrPUcccMWSiC-a4K9vVqxSaZLJZjE0ICpYp9jvhHlHtPYKDZlfBEZWRj9pDifWQAwPQGeU-72auVYDA6x_yYv5bcwawTGEs5uEOw1QZOk1TyQ5kIn-NC7A/s640/Logo_fedoralogo.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
In case you missed the announcement, Fedora 22 was released on Tuesday, 26 May. You can download it &lt;a href="https://getfedora.org/en/" target="_blank"&gt;here&lt;/a&gt; if you want to install a fresh copy.&lt;br /&gt;
&lt;br /&gt;
Or, if you're like me, you can upgrade your system in place using dnf and fedup. Here's a simple, step-by-step guide to upgrading your system.&lt;br /&gt;
&lt;h2&gt;
Step 1: Upgrade Your F21 System&lt;/h2&gt;
This goes without saying, but I'll say it anyway: make sure your system is up to date with F21. This will ensure an easier upgrade.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOoD5wAt4d5MLwClSu94LFFoMgursU3et38qcqt8Su3Jda_9WWoiALz1ERwOqe6GL-jaxThE_IF6fwE_u1AgBW6YLatWPh12j9mKeaviHdXFprfVz2WFL29GozuGRhLBPFBI6Y9k0E6CA/s1600/Screenshot_Fedora22_2015-05-29_13%253A41%253A25.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOoD5wAt4d5MLwClSu94LFFoMgursU3et38qcqt8Su3Jda_9WWoiALz1ERwOqe6GL-jaxThE_IF6fwE_u1AgBW6YLatWPh12j9mKeaviHdXFprfVz2WFL29GozuGRhLBPFBI6Y9k0E6CA/s640/Screenshot_Fedora22_2015-05-29_13%253A41%253A25.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Using Yum To Do A Distribution Synchronization&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h3&gt;
Step 2: Install FedUp&lt;/h3&gt;
&lt;a href="https://fedoraproject.org/wiki/FedUp" target="_blank"&gt;FedUp&lt;/a&gt; is the tool that does the heavy lifting for the upgrade. What it does it download the packages needed to upgrade your system from its current state to the released packages in Fedora 22.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifq8Fn98D5D9nYkThwxKw2NrS1e2wrpKYD1HOH7TGmXD4kO1VgkZpY6YtNF_wg8Ku0K8fhVsq6yIWnxBeSABF5dhyphenhyphengwqpbBmXE9lL9W0EM3wSV3QabRWPxe71_g4dvrs-H3-EyNYNAXpI/s1600/Screenshot_Fedora22_2015-05-29_13%253A43%253A08.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifq8Fn98D5D9nYkThwxKw2NrS1e2wrpKYD1HOH7TGmXD4kO1VgkZpY6YtNF_wg8Ku0K8fhVsq6yIWnxBeSABF5dhyphenhyphengwqpbBmXE9lL9W0EM3wSV3QabRWPxe71_g4dvrs-H3-EyNYNAXpI/s640/Screenshot_Fedora22_2015-05-29_13%253A43%253A08.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Installing The FedUp Package&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h3&gt;
Step 3: Use FedUp To Download The Upgrade Packages&lt;/h3&gt;
Now comes the first long task: downloading the upgrade packages. Depending on how much you have installed on your system, and the speed of your internet link, this could take a wee bit of time.&lt;br /&gt;
&lt;br /&gt;
FedUp has a few options for how it retrieves the packages for the upgrade. You can download the ISO install image and use it as a source, you can point it to a mount point on a shared filesystem (a great way to upgrade multiple systems would be to download the upgrade packages to an NFS drive and mount it from the various machines) to retrieve them, or you can point it to the network and tell it download the packages from a configured repository. We'll be using this last option.&lt;br /&gt;
&lt;br /&gt;
You'll also tell fedup to what version you want to upgrade your system. In this case, since we're going to Fedora 22, we'll tell it that with:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp;$ fedup --network 22&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqD2Ad3HWGXXbnv1xTilDwN7UG_h81kOJinrgVE3DomJ6yQI_897oNb6BVydr3YhuMice3ft_pPpvZ1andiXYc2jNg1O9lxucsuMTu4kzfo-_tTwFKs7Gp_EvTYL5TCgGiU3MlWRkAsmE/s1600/Screenshot_Fedora22_2015-05-29_13%253A47%253A06.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqD2Ad3HWGXXbnv1xTilDwN7UG_h81kOJinrgVE3DomJ6yQI_897oNb6BVydr3YhuMice3ft_pPpvZ1andiXYc2jNg1O9lxucsuMTu4kzfo-_tTwFKs7Gp_EvTYL5TCgGiU3MlWRkAsmE/s640/Screenshot_Fedora22_2015-05-29_13%253A47%253A06.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Running FedUp Over The Network&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
After this finishes, you have the option of aborting the upgrade process with:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;&amp;nbsp;$ fedup --resetbootloader&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
since FedUp will add a new entry to Grub's menu. But who's going to do that? We're here to upgrade! So now, reboot your system.&lt;br /&gt;
&lt;h3&gt;
Step 4: FedUp Does The Upgrade&lt;/h3&gt;
After rebooting your system, you'll see a new entry in Grub for the upgrade. You can still bypass the upgrade and choose one of your prior kernels. Of, by default, the system will select the upgrade path.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0diFTRZe6aoc2RmOpktim5UuH_qek7Mye2umD1GESppYt-BfH0Jv4jZFVUoqejxHFosNywetR_73ZBtho9djCVv0412c6057wAVVps6mVlohJq8QZZo3zSaHIuJ1U_KMhCroTwlfqQLo/s1600/Screenshot_Fedora22_2015-05-29_13%253A53%253A41.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0diFTRZe6aoc2RmOpktim5UuH_qek7Mye2umD1GESppYt-BfH0Jv4jZFVUoqejxHFosNywetR_73ZBtho9djCVv0412c6057wAVVps6mVlohJq8QZZo3zSaHIuJ1U_KMhCroTwlfqQLo/s640/Screenshot_Fedora22_2015-05-29_13%253A53%253A41.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The FedUp Grub Menu Option&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
Now is the time to go have a cuppa, a pint or whatever you do to pass the time. It's going to be a while as the system is upgraded.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Step 5: Here's Your Fedora 22 System...Enjoy!&lt;/h3&gt;
Once the install has finished, it will remove the upgrade option from Grub's menu and reboot your machine.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpEKroARYmA3N_1QEjaGjAVvV_EuDIRjTKouqS6hohU-Xc5Y6fCGoLQFTL_derPKjjBkRwU681xowgo-5bMorUfwfaVo76BbOYKzWs1rX7jf5IJmWrwA4KBgBDVx06VF8UxdUB3eMPK7E/s1600/Screenshot_Fedora22_2015-05-29_14%253A29%253A12.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpEKroARYmA3N_1QEjaGjAVvV_EuDIRjTKouqS6hohU-Xc5Y6fCGoLQFTL_derPKjjBkRwU681xowgo-5bMorUfwfaVo76BbOYKzWs1rX7jf5IJmWrwA4KBgBDVx06VF8UxdUB3eMPK7E/s640/Screenshot_Fedora22_2015-05-29_14%253A29%253A12.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;After The Reboot, No More Upgrade Option&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
You have now have a fully up-to-date and ready to run Fedora 22 system!&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh28TONxg3vPaQdga7LqxiKabHMtj9h3IOzj3loVSkOKsowW0sVG84sUgfx0hZFVYU7ExErKciBY9Or2fxIHayjMzFuqEIHamnTKUp8srhnzoIrAt80cEdeXp43T9RZyUFPU1r0msaKEFA/s1600/Screenshot_Fedora22_2015-05-29_14%253A31%253A28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh28TONxg3vPaQdga7LqxiKabHMtj9h3IOzj3loVSkOKsowW0sVG84sUgfx0hZFVYU7ExErKciBY9Or2fxIHayjMzFuqEIHamnTKUp8srhnzoIrAt80cEdeXp43T9RZyUFPU1r0msaKEFA/s640/Screenshot_Fedora22_2015-05-29_14%253A31%253A28.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2015/05/upgrading-fedora-from-f21-to-f22-with.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW1s20BFRkgSevcCaFd9v3LsrPUcccMWSiC-a4K9vVqxSaZLJZjE0ICpYp9jvhHlHtPYKDZlfBEZWRj9pDifWQAwPQGeU-72auVYDA6x_yYv5bcwawTGEs5uEOw1QZOk1TyQ5kIn-NC7A/s72-c/Logo_fedoralogo.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6537501841296627068</guid><pubDate>Wed, 18 Feb 2015 15:27:00 +0000</pubDate><atom:updated>2015-02-18T15:58:53.634-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">apache</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">messaging</category><category domain="http://www.blogger.com/atom/ns#">programming</category><category domain="http://www.blogger.com/atom/ns#">qpid</category><category domain="http://www.blogger.com/atom/ns#">ruby</category><title>Ruby Messaging Part 1: Know The Players, Know The Game</title><description>Hey, all. Here's a new series of blog posts I've been thinking about for a few weeks now. It's a series where I'm hoping to introduce you to a bit of work I've been doing lately on the Ruby messaging front with &lt;a href="http://qpid.apache.org/proton/index.html" target="_blank"&gt;Qpid Proton&lt;/a&gt;. Specifically, I've been working on a low-level set of APIs dubbed the "engine APIs". They are a close analog to elements in the AMQP protocol specification, so a knowledge of one will help in understanding the other.&lt;br /&gt;
&lt;br /&gt;
In this first post I'm going to introduce you to the main players in the game and how they each represent aspects of the &lt;a href="http://www.amqp.org/" target="_blank"&gt;AMQP&lt;/a&gt; messaging specification. Then I'll share a very small example application that accepts a connection from a remote container, but does nothing else for now. This application we can grow over the process of these posts until we have fully functional application.&lt;br /&gt;
&lt;h2&gt;
The Logical Components&lt;/h2&gt;
Working from the outside in, we have the following pieces:&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;container&lt;/b&gt;&amp;nbsp;is either a producer, a consumer, both a producer and a consumer, or a queue. As their names imply, producers and consumers either produce (send) messages or else consume (receiver) messages, or both, as is the case with most messaging containers.&lt;br /&gt;
&lt;br /&gt;
A container that primarily produces/consumers messages is going to be an application that uses messaging as a means of coordinating its efforts with other applications. An example, which I'll develop over the course of these blog posts, is a traffic light system which is designed to work with the local municipality's emergency needs.&lt;br /&gt;
&lt;br /&gt;
A container that acts as a queue would be a broker, communications bridge or similar application. It's not the endpoint for the bulk of the messages it receives, but is really a conduit through which messages flow on their way to their true endpoint; i.e., it stores and then forwards messages. Examples would include the &lt;a href="http://qpid.apache.org/components/cpp-broker/index.html" target="_blank"&gt;Qpid C++ broker&lt;/a&gt; and the &lt;a href="http://qpid.apache.org/components/dispatch-router/index.html" target="_blank"&gt;Qpid Dispatch router&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Containers create &lt;b&gt;connections&lt;/b&gt; to, or accept&amp;nbsp;from, other containers. The connection is how data actually flows in between the two containers and is broken down into constituent pieces, like the layers of an onion. But the details of that flow are outside of the scope of this series of posts.&lt;br /&gt;
&lt;br /&gt;
Within connections are &lt;b&gt;sessions&lt;/b&gt;. A session will have a pair of channels for sending and receiving data.&lt;br /&gt;
&lt;br /&gt;
Connections and session are thought of as &lt;b&gt;endpoints&lt;/b&gt;&amp;nbsp;which hold incoming messages and which hold the last known state information for outgoing messages.&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;channel&lt;/b&gt;&amp;nbsp;is a unidirectional (one way) means of sending messages. The reason why a session contains a pair of channels is to allow for bidirectional (two way) communcation.&lt;br /&gt;
&lt;br /&gt;
The&amp;nbsp;&lt;b&gt;terminus&lt;/b&gt;&amp;nbsp;maintains the state information for incoming and outgoing &lt;b&gt;messages&lt;/b&gt;&amp;nbsp;that flow over the link. A channel will have a source and a target terminus.&lt;br /&gt;
&lt;br /&gt;
The &lt;b&gt;link&lt;/b&gt;&amp;nbsp;is the where the actual protocol work is done, transmitting the message from source to target. It ties together the termini of a channel.&lt;br /&gt;
&lt;br /&gt;
So, to summarize:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;A container is an application that produces, consumes or queues messages.&lt;/li&gt;
&lt;li&gt;A connection is how two containers communicate with each other.&lt;/li&gt;
&lt;li&gt;A connection has one or more sessions, which pair up unidirectional channels to allow bidrectional communication.&lt;/li&gt;
&lt;li&gt;A channel sends data from one endpoint to the other over a link unidirectionally.&lt;/li&gt;
&lt;li&gt;A channel has a terminus which maintains the state information on each end of its link.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Translating To Ruby Classes&lt;/h2&gt;
So now that we know the big picture pieces from the specification, I'll translate that knowledge to the &lt;a href="https://github.com/mcpierce/Proton/tree/master/proton-c/bindings/ruby" target="_blank"&gt;Proton Ruby&lt;/a&gt; engine work I've been done.&lt;br /&gt;
&lt;br /&gt;
There is no analog (at this time) in the library for a container.&lt;br /&gt;
&lt;br /&gt;
The &lt;b&gt;Qpid::Proton::Connection&lt;/b&gt; class represents the connection between containers. With it you can start and stop working with a remote container, create new sessions, retrieve the next session which has pending work and also the next link with pending work to process. You can also access the transport engine, which is itself the topic for another post.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
The&amp;nbsp;&lt;b&gt;Qpid::Proton::Session&lt;/b&gt;&amp;nbsp;class is the session analog. With it you can start and stop sessions with the remote container, create endpoints to send and receive messages, peek at how many incoming and outgoing bytes there are as well as access the parent connection.&lt;br /&gt;
&lt;br /&gt;
The &lt;b&gt;Qpid::Proton::Sender&lt;/b&gt; and &lt;b&gt;Qpid::Proton::Receiver&lt;/b&gt; classes are used for sending and receiving instances of &lt;b&gt;Qpid::Proton::Message&lt;/b&gt;, respectively.&lt;br /&gt;
&lt;h2&gt;
Additional Classes&lt;/h2&gt;
In the Ruby library there are additional classes that work with the specification analogs to tie things together: the Transport and the Collector.&lt;br /&gt;
&lt;br /&gt;
The &lt;b&gt;Qpid::Proton::Transport&lt;/b&gt; class is the protocol engine. It processes incoming and outgoing bytes for a connection, and publishes events as that connection's state evolves over time.&lt;br /&gt;
&lt;br /&gt;
The &lt;b&gt;Qpid::Proton::Collector&lt;/b&gt; class is a FIFI queue which holds the events fired by the transport. It can be queried by the container to find the oldest event.&lt;br /&gt;
&lt;h2&gt;
An Example Application: The Traffic Light Manager&lt;/h2&gt;
Following is a simple Ruby application that accepts incoming connections and starts an AMQP dialog follows. It accepts a TCP connection, creates a connection and related objects and then begins looking at events to process.&lt;br /&gt;
&lt;br /&gt;
Bear in mind that this application is by no means the best example of how to write such an application, but is only used as a means of demonstrating how the pieces we're shown here fit together. A more details example will be developed in follow up posts.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;require 'qpid_proton'&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;require 'socket'&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;server = TCPServer.new(5672) # accept connections on the default AMQP port&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;# start an infinite loop&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;loop do&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; # spawn a new thread for each incoming client&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; Thread.new(server.accept) do |client_socket|&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # Create a connection object, a collector for any&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # events, and a transport to process&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;the data&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # flowing over the wire.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; conn = Qpid::Proton::Connection.new&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; collector = Qpid::Proton::Collector.new&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; conn.collect(collector)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; transport = Qpid::Proton::Transport.new&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # details of moving data between the client socket&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # and the transport are excluded here&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; #&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # instead, we'll just jump right to processing events&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; # get the next event&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; event = collector.peek&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; unless event.nil?&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; # do something here, a detail for a later post&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; # remove the event we've processed and get the next&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; collector.pop&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; event = collector.peek&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; end&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; end&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;end&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2015/02/ruby-messaging-part-1-know-players-know.html</link><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-7280650780284738716</guid><pubDate>Fri, 29 Aug 2014 13:56:00 +0000</pubDate><atom:updated>2014-08-29T09:56:52.184-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">command line</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">hardware</category><category domain="http://www.blogger.com/atom/ns#">laptop</category><title>Get Your Battery's Serial Number From A Terminal</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMft4YfXwavjDymQlM7lBM7mCmoY9pyNpVnJsKrFDMMpnWS85epyTa4HDfh58-D4RQbZjgO2UFZ5YfxYk-3AVpKiY6Xxk7iME2G5-UVwsQNDUi1stl9Y6wiChke0Srt13kvZW441doumw/s1600/images_articles_fedora.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMft4YfXwavjDymQlM7lBM7mCmoY9pyNpVnJsKrFDMMpnWS85epyTa4HDfh58-D4RQbZjgO2UFZ5YfxYk-3AVpKiY6Xxk7iME2G5-UVwsQNDUi1stl9Y6wiChke0Srt13kvZW441doumw/s1600/images_articles_fedora.jpg" height="194" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
For my work laptop (Lenovo T530) I've been seeing the battery life quickly declining in the past few weeks. I've been meaning to check the warranty on it but, every time I think about it, I'm ON the laptop at work and don't want to have to undock it to get the serial number.&lt;br /&gt;
&lt;br /&gt;
I figured I'd just get it from the command line somehow. And that's what I found using the &lt;b&gt;upower&lt;/b&gt;&amp;nbsp;command.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;O_o (1) [J:0/1113] mcpierce@mcpierce-laptop:acpi $&lt;/b&gt; upower -h&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;Usage:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; upower [OPTION...] UPower tool&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;Help Options:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -h, --help &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Show help options&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;Application Options:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -e, --enumerate &amp;nbsp; &amp;nbsp; &amp;nbsp;Enumerate objects paths for devices&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -d, --dump &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Dump all parameters for all objects&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -w, --wakeups &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Get the wakeup data&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -m, --monitor &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Monitor activity from the power daemon&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; --monitor-detail &amp;nbsp; &amp;nbsp; Monitor with detail&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -i, --show-info &amp;nbsp; &amp;nbsp; &amp;nbsp;Show information about object path&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; -v, --version &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Print version of client and daemon&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The first thing to do is to enumerate the list of power devices available using the &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;-e&lt;/b&gt;&lt;/span&gt; or &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;--enumerate&lt;/b&gt;&lt;/span&gt; command line option:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;^_^ [J:0/1115] mcpierce@mcpierce-laptop:acpi $&lt;/b&gt; upower --enumerate&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;/org/freedesktop/UPower/devices/line_power_AC&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;/org/freedesktop/UPower/devices/battery_BAT0&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here we can see two devices relating to power: &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;battery_BAT0&lt;/b&gt;&lt;/span&gt; and &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;line_power_AC&lt;/b&gt;&lt;/span&gt;. And I'm going to go out on a limb here and say that &lt;b&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;battery_BAT0&lt;/span&gt;&lt;/b&gt; is the one we want to interrogate.&lt;br /&gt;
&lt;br /&gt;
So now we ask it for information using the &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;-i&lt;/b&gt;&lt;/span&gt; or &lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;--show-info&lt;/b&gt;&lt;/span&gt; command line option:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;b&gt;^_^ [J:0/1116] mcpierce@mcpierce-laptop:acpi $&lt;/b&gt; upower --show-info /org/freedesktop/UPower/devices/battery_BAT0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; native-path: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;BAT0&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; vendor: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; LGC&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; model: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;45N1011&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; serial: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; XXXXX&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; power supply: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; yes&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; updated: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Fri 29 Aug 2014 09:20:05 AM EDT (1932 seconds ago)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; has history: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;yes&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; has statistics: &amp;nbsp; &amp;nbsp; &amp;nbsp; yes&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; battery&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; present: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; yes&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; rechargeable: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;yes&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; state: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fully-charged&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; energy: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;72.25 Wh&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; energy-empty: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0 Wh&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; energy-full: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 72.25 Wh&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; energy-full-design: &amp;nbsp;93.6 Wh&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; energy-rate: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2.82857 W&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; voltage: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 12.854 V&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; percentage: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;100%&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; capacity: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;77.1902%&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; technology: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;lithium-ion&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: inherit;"&gt;As we can see in the output the serial number for the laptop batter is listed, along with the vendor tag and model number.&lt;/span&gt;</description><link>http://mcpierce.blogspot.com/2014/08/get-your-batterys-serial-number-from.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMft4YfXwavjDymQlM7lBM7mCmoY9pyNpVnJsKrFDMMpnWS85epyTa4HDfh58-D4RQbZjgO2UFZ5YfxYk-3AVpKiY6Xxk7iME2G5-UVwsQNDUi1stl9Y6wiChke0Srt13kvZW441doumw/s72-c/images_articles_fedora.jpg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-8933224021446483438</guid><pubDate>Fri, 27 Sep 2013 14:13:00 +0000</pubDate><atom:updated>2013-09-27T10:13:07.179-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">birthday</category><category domain="http://www.blogger.com/atom/ns#">free software</category><title>Happy 30th Birthday, GNU!</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1trgL9jfzgqvE_J6BHC2UT9_Fq1OLgfi95lIvKxYAY9pB8WidJRqLG1gWJFui_47kg1jxn9uWtBPr1OD_1vohYvXZ1xqfGXaHxCS2_fMrTMOv5ilx9SXg_l7FLOjGgcXqCf018I1FeIE/s1600/gnu.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1trgL9jfzgqvE_J6BHC2UT9_Fq1OLgfi95lIvKxYAY9pB8WidJRqLG1gWJFui_47kg1jxn9uWtBPr1OD_1vohYvXZ1xqfGXaHxCS2_fMrTMOv5ilx9SXg_l7FLOjGgcXqCf018I1FeIE/s200/gnu.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
On 27 September 1983 &lt;a href="http://www.gnu.org/gnu/initial-announcement.html"&gt;Richard M. Stallman posted the following message&lt;/a&gt;&amp;nbsp;to a newsgroup:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;From CSvax:pur-ee:inuxc!ixn5c!ihnp4!houxm!mhuxi!eagle!mit-vax!mit-eddie!RMS@MIT-OZ&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;From: RMS%MIT-OZ@mit-eddie&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Newsgroups: net.unix-wizards,net.usoft&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Subject: new Unix implementation&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Date: Tue, 27-Sep-83 12:35:59 EST&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Organization: MIT AI Lab, Cambridge, MA&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Free Unix!&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Starting this Thanksgiving I am going to write a complete&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Unix-compatible software system called GNU (for Gnu's Not Unix), and&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;give it away free(1) to everyone who can use it.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Contributions of time, money, programs and equipment are greatly&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;needed.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;To begin with, GNU will be a kernel plus all the utilities needed to&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;write and run C programs: editor, shell, C compiler, linker,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;assembler, and a few other things. &amp;nbsp;After this we will add a text&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;formatter, a YACC, an Empire game, a spreadsheet, and hundreds of&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;other things. &amp;nbsp;We hope to supply, eventually, everything useful that&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;normally comes with a Unix system, and anything else useful, including&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;on-line and hardcopy documentation.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;GNU will be able to run Unix programs, but will not be identical&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;to Unix. &amp;nbsp;We will make all improvements that are convenient, based&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;on our experience with other operating systems. &amp;nbsp;In particular,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;we plan to have longer filenames, file version numbers, a crashproof&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;file system, filename completion perhaps, terminal-independent&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;display support, and eventually a Lisp-based window system through&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;which several Lisp programs and ordinary Unix programs can share a screen.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Both C and Lisp will be available as system programming languages.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;We will have network software based on MIT's chaosnet protocol,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;far superior to UUCP. &amp;nbsp;We may also have something compatible&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;with UUCP.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Who Am I?&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I am Richard Stallman, inventor of the original much-imitated EMACS&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;editor, now at the Artificial Intelligence Lab at MIT. &amp;nbsp;I have worked&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;extensively on compilers, editors, debuggers, command interpreters, the&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Incompatible Timesharing System and the Lisp Machine operating system.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I pioneered terminal-independent display support in ITS. &amp;nbsp;In addition I&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;have implemented one crashproof file system and two window systems for&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Lisp machines.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Why I Must Write GNU&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I consider that the golden rule requires that if I like a program I&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;must share it with other people who like it. &amp;nbsp;I cannot in good&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;conscience sign a nondisclosure agreement or a software license&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;agreement.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;So that I can continue to use computers without violating my principles,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I have decided to put together a sufficient body of free software so that&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I will be able to get along without any software that is not free.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;How You Can Contribute&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I am asking computer manufacturers for donations of machines and money.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;I'm asking individuals for donations of programs and work.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;One computer manufacturer has already offered to provide a machine. &amp;nbsp;But&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;we could use more. &amp;nbsp;One consequence you can expect if you donate&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;machines is that GNU will run on them at an early date. &amp;nbsp;The machine had&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;better be able to operate in a residential area, and not require&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;sophisticated cooling or power.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Individual programmers can contribute by writing a compatible duplicate&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;of some Unix utility and giving it to me. &amp;nbsp;For most projects, such&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;part-time distributed work would be very hard to coordinate; the&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;independently-written parts would not work together. &amp;nbsp;But for the&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;particular task of replacing Unix, this problem is absent. &amp;nbsp;Most&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;interface specifications are fixed by Unix compatibility. &amp;nbsp;If each&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;contribution works with the rest of Unix, it will probably work&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;with the rest of GNU.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;If I get donations of money, I may be able to hire a few people full or&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;part time. &amp;nbsp;The salary won't be high, but I'm looking for people for&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;whom knowing they are helping humanity is as important as money. &amp;nbsp;I view&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;this as a way of enabling dedicated people to devote their full energies to&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;working on GNU by sparing them the need to make a living in another way.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;For more information, contact me.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Arpanet mail:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; RMS@MIT-MC.ARPA&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;Usenet:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; ...!mit-eddie!RMS@OZ&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; ...!mit-vax!RMS@OZ&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;US Snail:&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Richard Stallman&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; 166 Prospect St&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; Cambridge, MA 02139&lt;/span&gt;</description><link>http://mcpierce.blogspot.com/2013/09/happy-30th-birthday-gnu.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1trgL9jfzgqvE_J6BHC2UT9_Fq1OLgfi95lIvKxYAY9pB8WidJRqLG1gWJFui_47kg1jxn9uWtBPr1OD_1vohYvXZ1xqfGXaHxCS2_fMrTMOv5ilx9SXg_l7FLOjGgcXqCf018I1FeIE/s72-c/gnu.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6754631657951389468</guid><pubDate>Tue, 10 Sep 2013 12:29:00 +0000</pubDate><atom:updated>2013-09-10T08:29:27.923-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">git</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">subversion</category><title>Git/Subversion Error: "Index mismatch: [hash] != [hash]"</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVCCuXzC2Z0J0fyYs-EeHnuDr1XXPluzsKEObWqa1a_0kH0y6htQ7QnAjO__XctKE5H0zqw8m0BkFdSX-5nNRXboxvxEFmWoo55TDcMCwk7O8-2v07HI4uFS3fDdEvMO5hR4Tgd87EfzA/s1600/subgit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="189" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVCCuXzC2Z0J0fyYs-EeHnuDr1XXPluzsKEObWqa1a_0kH0y6htQ7QnAjO__XctKE5H0zqw8m0BkFdSX-5nNRXboxvxEFmWoo55TDcMCwk7O8-2v07HI4uFS3fDdEvMO5hR4Tgd87EfzA/s400/subgit.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;
The Problem&lt;/h2&gt;
Our source code is stored in a Subversion repository (it's an Apache project) and I use Git to clone that repo for work. This morning I attempted to update my local repo when the following happened:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;^_^ [J:0/1003] mcpierce@mcpierce-laptop:Qpid (upstream) $ git svn rebase
Index mismatch: e5893616e68dba2bd8a730609d872f19517e0536 != 93c1bfda2ff4e72a1ae1fbc8374d42ebe107e1f5
rereading 695961e1cc7749916959f1f74db659e90e0d2dcc
 M qpid/cpp/src/qpid/broker/SessionState.h
 M qpid/cpp/src/qpid/broker/SemanticState.cpp
 M qpid/cpp/src/qpid/broker/SessionState.cpp
Author: pmoravec not defined in .git/authors.txt file
&lt;/pre&gt;
&lt;br /&gt;
The user "pmoravec" was recently added as a committer to the project and his first commit apparently threw my git clone of the subversion repository off.&lt;br /&gt;
&lt;h2&gt;
The Solution&lt;/h2&gt;
For me it was a simple solution. I simply had to pull down the updated authors.txt file from Apache that included pmoravec and replace the one in my git repo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;^_^ [J:0/1029] mcpierce@mcpierce-laptop:Qpid (master) $ wget http://git.apache.org/authors.txt
&lt;/pre&gt;
&lt;br /&gt;
Done and one, now I'm back to work.&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2013/09/gitsubversion-error-index-mismatch-hash.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVCCuXzC2Z0J0fyYs-EeHnuDr1XXPluzsKEObWqa1a_0kH0y6htQ7QnAjO__XctKE5H0zqw8m0BkFdSX-5nNRXboxvxEFmWoo55TDcMCwk7O8-2v07HI4uFS3fDdEvMO5hR4Tgd87EfzA/s72-c/subgit.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-521302467058346756</guid><pubDate>Thu, 22 Aug 2013 13:44:00 +0000</pubDate><atom:updated>2013-08-22T09:44:19.735-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">administration</category><category domain="http://www.blogger.com/atom/ns#">configuration</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Puppet: Defining A System, Adding A Package And Launching A Service</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirWPKKDV3kNt8TliSKZlGx6N15h3AJa80t876tSnmPQRjJGStwiaqZXqPvHGXA8_R_kDfHrG6l-p8wo6ttGc87NpabYwaD7Qa-jFZURwOsZ1musXXGW0o1NYuW6CJR04oxpMZbn3nft4E/s1600/puppet_labs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirWPKKDV3kNt8TliSKZlGx6N15h3AJa80t876tSnmPQRjJGStwiaqZXqPvHGXA8_R_kDfHrG6l-p8wo6ttGc87NpabYwaD7Qa-jFZURwOsZ1musXXGW0o1NYuW6CJR04oxpMZbn3nft4E/s400/puppet_labs.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
Previously I wrote &lt;a href="http://mcpierce.blogspot.com/2013/08/a-simple-puppet-31-setup.html"&gt;a simple blog post&lt;/a&gt; about setting up a &lt;a href="http://puppetlabs.com/"&gt;Puppet&lt;/a&gt; master and agent. In this post I'm going to write about how to add a simple service to your puppet master that will be installed (if necessary) and started (if necessary) on systems.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Step 1: Define the system on your Puppet master&lt;/h2&gt;
Before your Puppet master can do its work, it needs to first know what needs to be done and to whom.&lt;br /&gt;
&lt;br /&gt;
In your &lt;b&gt;/etc/puppet/manifests&lt;/b&gt; directory you'll want to create two files with the following content (remember: in my case the Puppet master's name is &lt;b&gt;earth&lt;/b&gt; and the Puppet client's name is &lt;b&gt;halo&lt;/b&gt;):&lt;br /&gt;
&lt;h3&gt;
site.pp&lt;/h3&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; import 'nodes.pp'&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; filebucket { main: server =&amp;gt; "earth.gateway.2wire.net" }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; File { backup =&amp;gt; main }&lt;br /&gt;&amp;nbsp; Exec { path =&amp;gt; "/usr/bin:/usr/sbin:/bin:/sbin" }&lt;/span&gt;&lt;br /&gt;
&lt;h3&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-family: inherit;"&gt;nodes.pp&lt;/span&gt; &lt;/span&gt;&lt;/h3&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; # nodes.pp&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; node default {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; include ntp&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; node 'halo.gateway.2wire.net' inherits default {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In this example the default system definition will install the sudo module. The definition for a server will inherit that definition and add to it the ntp module. And finally the definition for halo inherits the server definition and adds to it the bip module.&lt;br /&gt;
&lt;br /&gt;
In later posts I'll expand on the above to do more involved server definitions, specifically add modules that include files. But let's not get ahead of ourselves.&lt;br /&gt;
&lt;h2&gt;
Step 3: Add the module definition&lt;/h2&gt;
Before Puppet can do anything on the client it has to have more details on, in this case, the ntp module.&lt;br /&gt;
&lt;br /&gt;
To do that we first create the file &lt;b&gt;/etc/puppet/modules/tests/init.pp&lt;/b&gt; with the following content:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; class { 'ntp': }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Next we'll create the file &lt;b&gt;/etc/puppet/modules/ntp/manifests/init.pp&lt;/b&gt; with the following content:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; class ntp {&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; package { ntp: ensure =&amp;gt; installed }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file { "/etc/ntp.conf":&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; owner =&amp;gt; root,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; group =&amp;gt; root,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; mode =&amp;gt; 640,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; require =&amp;gt; Package["ntp"],&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; service { 'ntp':&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; name =&amp;gt; 'ntpd',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ensure =&amp;gt; running,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; enable =&amp;gt; true,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; subscribe =&amp;gt; File['/etc/ntp.conf'],&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In the configuration we ensure the package is installed, that, if the file &lt;b&gt;/etc/ntp.conf&lt;/b&gt; exists, the configuration is owned by user root and group root, that it has the proper file modes, and that if it doesn't exist the package named ntp is installed to provide it.&lt;br /&gt;
&lt;br /&gt;
The service stanza adds to the above a check for the actual service itself. If Puppet doesn't see a process named "ntpd" then it knows that the service isn't up and will launch it for you.&lt;br /&gt;
&lt;h2&gt;
Conclusion&lt;/h2&gt;
That's it! If you then launch the puppet agent on your client machine, you should see it apply the above configuration by installed the package named ntp.</description><link>http://mcpierce.blogspot.com/2013/08/puppet-defining-system-adding-package.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirWPKKDV3kNt8TliSKZlGx6N15h3AJa80t876tSnmPQRjJGStwiaqZXqPvHGXA8_R_kDfHrG6l-p8wo6ttGc87NpabYwaD7Qa-jFZURwOsZ1musXXGW0o1NYuW6CJR04oxpMZbn3nft4E/s72-c/puppet_labs.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-5407367208471255737</guid><pubDate>Mon, 19 Aug 2013 01:25:00 +0000</pubDate><atom:updated>2013-08-18T21:51:58.467-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">administration</category><category domain="http://www.blogger.com/atom/ns#">configuration</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>A Simple Puppet 3.1 Setup</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9OkccFKHUH_WTCEHaAEpL6KDTcts_h8s4bKeJOQm6LGsRRwdI34KFGYf1Ro09YqXtKxmICf98OK2ZrENAon-TUNuHnMJ8zLfi7hd-DYzpdm-HNFJvV61Lcw2IKLYga36vMJz1j173ano/s1600/puppet_labs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9OkccFKHUH_WTCEHaAEpL6KDTcts_h8s4bKeJOQm6LGsRRwdI34KFGYf1Ro09YqXtKxmICf98OK2ZrENAon-TUNuHnMJ8zLfi7hd-DYzpdm-HNFJvV61Lcw2IKLYga36vMJz1j173ano/s320/puppet_labs.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
Recently I got the notion of setting up a puppetized configuration system for my computers at home. I have two machines:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;earth - a Linux desktop, which will be the puppet client&lt;/li&gt;
&lt;li&gt;halo - a Linux server, which will be the puppet server as well as a client&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
My biggest frustration, though, was find a simple tutorial that would help me get Puppet up and running, the two machines talking, and a configuration pushing down onto the client.&lt;br /&gt;
&lt;br /&gt;
So after pulling from a few separate sources, here's what I found works. In a future post I'll write about how, after more frustration, I was able to get configurations pushing down onto the systems and how I setup version control on the puppet configurations themselves.&lt;br /&gt;
&lt;h2&gt;
Step 1: Install Puppet (Fedora 19)&lt;/h2&gt;
Not the hardest part, but you do need to be aware of what packages are out there. The two packages are &lt;b&gt;puppet&lt;/b&gt; and &lt;b&gt;puppet-server&lt;/b&gt;. The former is what you need on any system that will act as a client or agent, the latter on any system that will be offering up puppetized data.&lt;br /&gt;
&lt;br /&gt;
So, obviously, I installed puppet on halo, and puppet and puppet-server on earth.&lt;br /&gt;
&lt;h2&gt;
Step 2: Configuring The Puppet Master&lt;/h2&gt;
This is the first part that gave me headaches. Since I don't want to deal with external certificates, I just wanted something that would work for me in my private network.&lt;br /&gt;
&lt;br /&gt;
What I did was to configure earth to be it's own certificate authority with the following in &lt;b&gt;/etc/puppet/puppet.conf&lt;/b&gt;:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[main]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; logdir = /var/log/puppet&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rundir = /var/run/puppet&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ssldir = $vardir/ssl&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # self-signing certificates&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; server = earth.gateway.2wire.net&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; certname = earth.gateway.2wire.net&lt;/b&gt;&lt;br /&gt;[master]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; reports = store, http&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; modulepath=/etc/puppet/modules:/usr/share/puppet/modules&lt;br /&gt;&lt;br /&gt;[agent]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; classfile = $vardir/classes.txt&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; localconfig = $vardir/localconfig&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2&gt;
Step 3: Exchanging SSL Certificates With The Agent&lt;/h2&gt;
Here is where there was a decided lack of examples online. And the Puppet website didn't help at all, especially with recovering things after a failure occurred.&lt;br /&gt;
&lt;br /&gt;
The steps to follow are:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;unless you have your own DNS, add the fully qualified hostnames of each machine in the other's &lt;b&gt;/etc/hosts&lt;/b&gt; file; i.e., for me I had to put &lt;b&gt;earth.gateway.2wire.net&lt;/b&gt; in halo's file, and &lt;b&gt;halo.gateway.2wire.net&lt;/b&gt; in earth's, then&lt;/li&gt;
&lt;li&gt;open two terminals on your puppet master (in my case, on earth) and one on your puppet agent (in my case, on halo), then&lt;/li&gt;
&lt;li&gt;start up in one puppet master terminal a master using the command line:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;puppet master --no-daemonize --verbose&lt;/span&gt; &lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;on the puppet agent terminal start an agent using the command line:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;puppet agent -t --no-daemonize --verbose&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;you'll see some messages about exchanging the SSL credentials and then a note that no certificate is waiting, at which point in the other puppet master terminal window you'll do:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;puppet cert sign halo.gateway.2wire.net&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
At this point your machines will have shared SSL credentials and will be able to talk to each other.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Step 4: How To Recover If Something Goes Wrong&lt;/h2&gt;
If you start getting messages about the keys being wrong on the agent side, the easiest thing to do is to delete the &lt;b&gt;/var/lib/puppet/ssl/&lt;/b&gt; directories on &lt;b&gt;BOTH&lt;/b&gt; machines. This way you no longer have any data about the other system and can start over with a clean slate.</description><link>http://mcpierce.blogspot.com/2013/08/a-simple-puppet-31-setup.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9OkccFKHUH_WTCEHaAEpL6KDTcts_h8s4bKeJOQm6LGsRRwdI34KFGYf1Ro09YqXtKxmICf98OK2ZrENAon-TUNuHnMJ8zLfi7hd-DYzpdm-HNFJvV61Lcw2IKLYga36vMJz1j173ano/s72-c/puppet_labs.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-1277449874075357183</guid><pubDate>Sun, 04 Aug 2013 14:39:00 +0000</pubDate><atom:updated>2013-08-05T08:07:04.552-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Grouping Channels In Weechat By Network</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQUoRgCSZLeNths0wxRJ27kRL8WSv7ap3mlcVN6wB0ezuqKuvq8A_c8r0oaqTMrSR-1QkYxN_33YuM6O8piH1E8bDaT9ADbiYEdgL6PHO8JQlXQKPw3Ov6IjKbpVGisuw04V48Z0Im1Ok/s1600/8222_large.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQUoRgCSZLeNths0wxRJ27kRL8WSv7ap3mlcVN6wB0ezuqKuvq8A_c8r0oaqTMrSR-1QkYxN_33YuM6O8piH1E8bDaT9ADbiYEdgL6PHO8JQlXQKPw3Ov6IjKbpVGisuw04V48Z0Im1Ok/s400/8222_large.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
One of the things that's kept me from switching from Xchat to Weechat for IRC was that I couldn't keep my channels grouped together by network. Where I work we have internal IRC channels with the same name as public IRC channels, and it was confusing to look at the window and figure out which was internal or not.&lt;br /&gt;
&lt;br /&gt;
Fortunately, I found a way to change that in Weechat and so have switched over to it exclusively. Here's how:&lt;br /&gt;
&lt;h3&gt;
Install the buffers.pl plugin.&lt;/h3&gt;
The buffers plugin lets you configure how the various buffers are displayed.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; /script install buffers.pl&lt;/span&gt;&lt;br /&gt;
&lt;h3&gt;
Tell buffers.pl to show the IRC network name.&lt;/h3&gt;
By default buffers.pl only shows the channel name (#name). To group channels together, you need to enable showing the fullly qualified channel name (network#name):&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; /set buffers.look.short_names off&lt;/span&gt;&lt;br /&gt;
&lt;h3&gt;
Sort channels by name and not numbers.&lt;/h3&gt;
&lt;div&gt;
This groups the channels together by their server name. Otherwise they're grouped by the order in which they were opened. So if you open a channel in Freenode, say, after opening one in OFTC then the channel in Freenode will fall after OFTC and not get put with the other Freenode channels.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;&amp;nbsp; /set buffers.look.sort name&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
That's it! Now your channels are grouped together by network.&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/08/grouping-channels-in-weechat-by-network.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQUoRgCSZLeNths0wxRJ27kRL8WSv7ap3mlcVN6wB0ezuqKuvq8A_c8r0oaqTMrSR-1QkYxN_33YuM6O8piH1E8bDaT9ADbiYEdgL6PHO8JQlXQKPw3Ov6IjKbpVGisuw04V48Z0Im1Ok/s72-c/8222_large.png" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-1445707068766560226</guid><pubDate>Tue, 09 Jul 2013 13:04:00 +0000</pubDate><atom:updated>2013-07-09T09:04:09.640-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">laptop</category><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">video</category><title>Fedora 19: Nouveau Drivers Are Fixed!</title><description>At work a few months ago I got a new laptop: a &lt;a href="http://shop.lenovo.com/us/en/laptops/thinkpad/t-series/t530/index.html"&gt;Lenovo T530&lt;/a&gt; with the Optimus Technology display chipset:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
For more taxing multimedia and gaming use, NVIDIA's line of NVS with Optimus graphics cards provide the graphical processing boost you need. Optimus technology automatically configures your system to provide for the most optimal experience with your games or applications while also maintaining battery life.&lt;/blockquote&gt;
The problem that I hit was that the Nouveau drivers would NOT work nicely with this video setup. If I disabled the nVidia hardware and run only the Intel video chipset things worked beautifully, but I could not use my docking station since it doesn't support external displays. If I enabled the nVidia hardware only then I could drive my external monitors but couldn't go into standby mode, couldn't dock and then undock, and inevitably the display would get borked (&lt;a href="http://bugzilla.redhat.com/show_bug.cgi?id=948079"&gt;BZ#948079&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
To deal with the problem, I had no choice but to start using the closed-source nVidia drivers. They're freely licensed, but being closed source just goes against the spirit of what I support. And it also has the annoying habit of requiring me to run the nVidia configuration tool when I dock my laptop in order to enable the external monitors rather than just switching to them automatically, which is what the nouveau drivers do.&lt;br /&gt;
&lt;br /&gt;
So when I upgraded my laptop with &lt;a href="http://fedoraproject.org/get-fedora"&gt;Fedora 19 (Schroedinger's Cat)&lt;/a&gt;, I was happy to find that the bug had, at some point, been quietly fixed!&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0gFvK5lmBtupQphDKDuPk8zfBwKUz8t42MZ4LyRA1d_ORyVsDL0eahpA9f6ZLIbnPnqUs-V4KbxPkmIlF-76bSe7_9Yo4lNvVZ0FBs8ftNCGsg1eLlH4WEUTVNri-ITvGPCC2Us74GyY/s1600/fedora-19-logo_thumb.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0gFvK5lmBtupQphDKDuPk8zfBwKUz8t42MZ4LyRA1d_ORyVsDL0eahpA9f6ZLIbnPnqUs-V4KbxPkmIlF-76bSe7_9Yo4lNvVZ0FBs8ftNCGsg1eLlH4WEUTVNri-ITvGPCC2Us74GyY/s1600/fedora-19-logo_thumb.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/07/fedora-19-nouveau-drivers-are-fixed.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0gFvK5lmBtupQphDKDuPk8zfBwKUz8t42MZ4LyRA1d_ORyVsDL0eahpA9f6ZLIbnPnqUs-V4KbxPkmIlF-76bSe7_9Yo4lNvVZ0FBs8ftNCGsg1eLlH4WEUTVNri-ITvGPCC2Us74GyY/s72-c/fedora-19-logo_thumb.jpg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6510740029002963210</guid><pubDate>Wed, 05 Jun 2013 15:56:00 +0000</pubDate><atom:updated>2013-06-05T11:56:22.448-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">essay</category><category domain="http://www.blogger.com/atom/ns#">philosophy</category><title>Omniscience Vs. Free Will: A VERY Old Web Page I Wrote</title><description>Years ago I wrote the following about the logical inconsistency between free will and omniscience. I hadn't thought about or read the page in a long time, but it came to mind today when someone sent an email asking to translate the website I had back in the early 2000s.&lt;br /&gt;
&lt;h2&gt;
The Basic Premise&lt;/h2&gt;
The concepts of omniscience and free will and mutually exclusive. If there exists omniscience, then no being is able to make choices other than those known by the omniscient being. If free will exists, then there can be no such thing as omniscience.&lt;br /&gt;&lt;h3&gt;
What Is Omniscience?&lt;/h3&gt;
&lt;div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;b&gt;Omniscience:&lt;/b&gt; having infinite awareness, understanding and insightpossessed of universal or complete knowledge&lt;/blockquote&gt;
A being with omniscience is one that has complete knowledge of the universe. There can be no knowledge that this being does not possess. Nothing for it to learn since learning would require a form of limited knowledge where information is not contained in one state and then is contained in another state.&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
What Is Free Will?&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;b&gt;Free Will:&lt;/b&gt; freedom of humans to make choices that are not determined by prior causes or divine intervention&lt;/blockquote&gt;
In order for a being to have free will, it must be able to choose any possible action when a decision action is presented. Any choice that is possible must be allowed without external intervention or influence.&lt;br /&gt;&lt;h3&gt;
So, What's The Problem?&lt;/h3&gt;
With omniscience, all knowledge is known, including the choice made by each being at every stage. It is not possible for a being to make a choice other than what is already known via omniscience, thereby precluding any chance for free will. A being cannot make any choice that would contradict omniscience, since omniscience by nature requires that all choices be predetermined.&lt;br /&gt;&lt;h2&gt;
So what?&lt;/h2&gt;
&lt;/div&gt;
&lt;h3&gt;
What if the omniscient being is outside of our space-time?&lt;/h3&gt;
&lt;div&gt;
Well, whether that being is confined to our universe or is somehow able to exist outside of our universe, if it has omniscience with regards to our universe then it directly affects the free will of beings within out universe. The contradiction comes from our choices being decided before they are made within our flow of time.&lt;br /&gt;&lt;h3&gt;
Can't the being outside of our universe view our choices to learn them?&amp;nbsp;&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
Sure. But, that is not omniscience: it is limited knowledge. Omniscience is, by definition, infinite knowledge. Since it is impossible to combine enough finite elements to reach infinity, a being cannot reach omniscience by learning.&lt;br /&gt;&lt;h2&gt;
An Example Of The Contradiction&lt;/h2&gt;
I wake up and decide to have oatmeal for breakfast rather than eggs.&lt;/div&gt;
&lt;h3&gt;
Have I made a choice of my own free will?&lt;/h3&gt;
&lt;div&gt;
That depends. If there is a being with omniscience, then my choice to have oatmeal was dictated before the morning in question. I did not make a choice; instead, I acted out a script that only superficially looks like free will. The choice to have oatmeal was made by something other than myself and I could only follow along acting out a script and not making a choice of my own free will.&lt;br /&gt;&lt;br /&gt;The problem is that omniscience requires 100% perfect knowledge. This leaves no room for variation. When each decision fork is reached, only one branch can be followed: the one previously decided via omniscience.&lt;br /&gt;&lt;h3&gt;
But, Don't We Have Free Will?&lt;/h3&gt;
Apparently, yes, we do. But, that's not the issue. The contradiction does not mean that we do not have free will. Since we seem to have free will, the only way to resolve the contradiction is to admit that there cannot exist a being with omniscience.&lt;br /&gt;&lt;h3&gt;
Can Omniscience Be Learned?&lt;/h3&gt;
No. The process of learning is based on having limited knowledge. Since omniscience is the state of having infinite knowledge, you can't accumulate knowledge until you finally have infinite knowledge. The problem is that there is no such thing as infinity minus one. How can you be one unit of knowledge away from having infinite knowledge?&lt;br /&gt;&lt;h3&gt;
Can't A Being Have Foreknowledge Instead?&lt;/h3&gt;
Sure! But, foreknowledge is not the same as omniscience. Foreknowledge is merely the knowledge of something in advance, and is based on limited knowledge. A being can have foreknowledge without being omniscience.&lt;br /&gt;&lt;br /&gt;You do not become omniscient by watching a movie backwards, for example. Omniscience would require a being to know the entire movie inside and out before ever actually observing the film.&lt;br /&gt;&lt;h3&gt;
Why Can't A Being Have Progressive Omniscience?&lt;/h3&gt;
Progressive omniscience is a meaningless phrase. This would be knowledge gained, and is discussed above under the header Can Omniscience Be Learned?&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/06/omniscience-vs-free-will-very-old-web.html</link><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6802541567107937241</guid><pubDate>Fri, 17 May 2013 14:05:00 +0000</pubDate><atom:updated>2013-05-17T13:28:23.978-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">podcasting</category><title>Podcasting 101: Creating A Podcast Website</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s1600/podcasting.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s400/podcasting.jpeg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
In this installment, I'll help you to understand how to create a single episode of your new podcast by taking you through the steps I follow. We will assume that you've already recorded, mixed and exported the audio.&lt;br /&gt;
&lt;br /&gt;
First things first, though, you'll need to create a blog for your podcast. Then we will setup a Feedburner redirector for the podcast so that, should you ever need to move the podcast to a different hosting site, you won't have to force your listeners to manually change their feed location.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Creating The Podcast Blog Site (With Blogger.com)&lt;/h2&gt;
I choose blogger.com for no other reason than I use it myself for both of my shows. Though I'm sure the steps I describe will apply to other sites later.&lt;br /&gt;
&lt;br /&gt;
If you have a Google account already, you're halfway to creating your blog. If not, register for one by signing up for Gmail.&lt;br /&gt;
&lt;br /&gt;
Go to &lt;a href="http://www.blogger.com/"&gt;blogger.com&lt;/a&gt;. There you will see a button in the upper-left corner that says "New Blog".&lt;br /&gt;
&lt;br /&gt;
Click it.&lt;br /&gt;
&lt;br /&gt;
Hopefully you've chosen a decent name for your podcast, something catching, creative and fresh. For now we won't worry about creating a podcast domain name, so in the field marked "Address" enter a unique, simplified version of your podcast's name.&lt;br /&gt;
&lt;br /&gt;
Click "Create Blog!"&lt;br /&gt;
&lt;br /&gt;
Now we have a way to share the episodes.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Adding Your Custom Domain&lt;/h2&gt;
On the blog list screen, click on the blog's name, and you will see a page with options such as "Post", "Pages", "Earnings", etc. Towards the bottom of this list is "Settings".&lt;br /&gt;
&lt;br /&gt;
Click it.&lt;br /&gt;
&lt;br /&gt;
Under the "Publishing" heading you'll want to click "Add a custom domain". This will open an input field that will let you put in the hostname you've setup (instructions are in a future installment) for your podcast's blog site.&lt;br /&gt;
&lt;br /&gt;
For example, at A Little Dead Podcast our blog's hostname is &lt;a href="http://blog.alittledead.com/"&gt;http://blog.alittledead.com&lt;/a&gt;. So, in this field, I have "blog.alittledead.com". What this does is tell Blogger that it should make all pages and blog posts use a URL relative to the address entered.&lt;br /&gt;
&lt;br /&gt;
If you don't understand what that means, it's okay. You can trust me on this.&lt;br /&gt;
&lt;br /&gt;
Now you have an address you can share with listeners to tell them where to go to find your show.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Setting Up A Feed Redirector &lt;/h2&gt;
Feedburner is a great, useful tool for podcasters. It lets you see how many times your episodes have been downloaded, from what countries the downloads have occurred, and more.&lt;br /&gt;
&lt;br /&gt;
Here, though, we're going to setup the redirector itself. But there's a lot more than Feedburner can do for you, which we will explore in another installment.&lt;br /&gt;
&lt;br /&gt;
In a separate tab on your browser, go to the website: &lt;a href="http://feedburner.google.com/"&gt;feedburner.google.com&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
You'll see the text "Burn a feed right now" along with an input field and a checkbox that says "I am a podcaster".&lt;br /&gt;
&lt;br /&gt;
Mark the checkbox.&lt;br /&gt;
&lt;br /&gt;
In the input field, enter the URL for your podcast. If you don't have a custom domain and used Blogger then this is the name of your podcast followed by .blogger.com.&lt;br /&gt;
&lt;br /&gt;
So, for example, if you gave your blog the name "testcast2" in the earlier step, then here you would enter &lt;b&gt;testcast2.blogger.com&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Click "Next". If you entered the right information then you should be presented with two options under the title "&lt;b&gt;Identify Feed Source&lt;/b&gt;":&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;an atom feed, and&lt;/li&gt;
&lt;li&gt;an RSS feed&lt;/li&gt;
&lt;/ul&gt;
You want to select the &lt;b&gt;RSS feed&lt;/b&gt; here, and click &lt;b&gt;Next&lt;/b&gt;. On the next screen enter the title for your podcast redirector, and also pick and address for it. For this latter entry, pick something simple, like the name of your podcast's abbreviated name on your host site. So, again, in this example, since I named the podcast "testcast2" on blogger.com, I would enter "testcast2" as the feed address.&lt;br /&gt;
&lt;br /&gt;
Click &lt;b&gt;Next&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
On the congratulations page you'll see a feed URL at the top that looks something like this:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
http://feeds.feedburner.com/testcast2&lt;/blockquote&gt;
Copy this address and go back to you blog's setup page. Under the Settings-&amp;gt;Other-&amp;gt;Site Feed section, click &lt;b&gt;Add&lt;/b&gt; for the "Pod Feed Redirect URL" and paste the URL into the input field shown.&lt;br /&gt;
&lt;br /&gt;
Click the "Save Settings" button in the upper-right corner.&lt;br /&gt;
&lt;br /&gt;
Back on the Feedburner page, click through all of the the &lt;b&gt;Next&lt;/b&gt; buttons until you're back to the main page.&lt;br /&gt;
&lt;br /&gt;
There! Now you have a podcast blog as well as an active feed. To verify the feed as working, copy the feedburner URL into your browser. If everything is setup correctly then you should see page that shows you an empty feed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Future Installments&lt;/h2&gt;
In a future installment, I'll show you how to configure Feedburner to do things like alter your RSS feed for iTunes, inserting elements that Apple specifically wants to have present, how to register the podcast with iTunes, how to change your feed to track statistics for episodes entries separately from non-episode entries on your blog (we post news that I want to view separately when looking at the audience breakdown).&lt;br /&gt;
&lt;br /&gt;
Also how to use Project Wonderful for making the podcast's website help pay for itself while growing your audience. &lt;br /&gt;
&lt;br /&gt;
Till then, have fun with your new website!</description><link>http://mcpierce.blogspot.com/2013/05/podcasting-101-creating-podcast-website.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s72-c/podcasting.jpeg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6371003483439157638</guid><pubDate>Thu, 16 May 2013 15:50:00 +0000</pubDate><atom:updated>2013-05-16T11:50:49.181-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">podcasting</category><title>Podcasting 101: What Are The Things I Need?</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s1600/podcasting.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s320/podcasting.jpeg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
The first question, and probably the most challenging one for the new podcast host, is what are the things I need to create and share my show?
&lt;br /&gt;
&lt;br /&gt;
What you (minimally) need is:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;equipment to record and edit your episodes&lt;/li&gt;
&lt;li&gt;a means of posting the episodes themselves online&lt;/li&gt;
&lt;li&gt;a way of letting listeners/viewers know that the new episodes are available&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Here's what I use for my shows. I'm not going to talk about video equipment since that's a whole world different when it comes to recording and editing than audio equipment. I'll talk about that in a future installment.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
Recording Equipment&lt;/h2&gt;
&lt;h3&gt;
Software&lt;/h3&gt;
&lt;div&gt;
To record episodes, you'll want something that allows you to record multiple tracks of audio.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For normal recordings I use Audacity, available &lt;a href="http://audacity.sourceforge.net/" target="_blank"&gt;here&lt;/a&gt;. It's free, available on Linux, Windows and the Mac, and supports all standard audio formats. It uses its own format for locally storing a project, but you can export the audio to MP3, Ogg Vorbis, WAV, etc. Though for podcasts I recommend MP3.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
And during exports, you can add most ID3 meta data to the episode.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In a later installment I'll talk about how to use Audacity in more detail.&lt;/div&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;
Microphone&lt;/h3&gt;
&lt;div&gt;
Don't skimp on this piece, but do pick something in your budget. Remember: you get what you pay for, and buying a cheap microphone results in bad audio quality. You want something that produces a warm sound. A decent USB headset with built-in microphone (like my Microsoft Lifechat LX-3000) works great for this, and you can use it for other things such as recording interviews, which is another installment.&lt;/div&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;
Other Equipment&lt;/h3&gt;
&lt;div&gt;
If you want to use a standard studio microphone (which is what I do for normal episodes), you'll want to also get a USB mixer. A certain cohost of mine gave me a very nice microphone and mixer setup that matches what he uses for his segments. And I found that it provides the best audio quality to date for the show.&lt;/div&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
Posting Episodes Online&lt;/h2&gt;
&lt;div&gt;
After you've produced your episode, you need to put it up online so listeners can get to it.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The cheapest way to do this is to post the episodes on &lt;a href="http://archive.org/"&gt;archive.org&lt;/a&gt;. The only caveat is that you need to release your audio under some sort of free or unencumbered license. My shows are all released under Creative Commons Share-Alike Non-Commercial (CC-SA-NC) licenses. People are free to take the audio, cut it up and use bits of it, so long as it's for non-commercial results (they can't charge for the results), they have to give a reference back to us and they have to allow others to take their work and do the same.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
After you've uploaded your episode to archive.org, you can then get a link directly to the MP3 file that you would put into your podcast feed. That way listeners can download the file. More on that in a later installment.&lt;/div&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
Notifying Listeners&lt;/h2&gt;
&lt;div&gt;
To notify listeners that you have a new episode available, you have to create an RSS feed, which is simpler than it sounds. The first step is to create a blog, and the second is to add it to podcast aggregators like iTunes, which will also be a later installment.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Another thing to do is to setup a feed redirector, such as &lt;a href="http://feedburner.google.com/" target="_blank"&gt;Feed Burner&lt;/a&gt;, and tell listeners to subscribe to that. Setting that up is also a later installment.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The cheapest thing is to create a blog on a free site like &lt;a href="http://www.blogger.com/home" target="_blank"&gt;Blogger&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
After you've uploaded your MP3 file to archive.org, you create a new blog entry on your site. In the lower-right corner where it says "Links" you copy the MP3's URL (being sure to change "https" to "http" if your URL has that) into both the "Title Link" and "Enclosure Link" fields, and setting the mime type to "audio/mp3".&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Once you publish the new blog entry, anybody who is subscribed to the RSS feed for the blog will be notified that a new episode is available.&lt;/div&gt;
&lt;h2&gt;
Conclusion&lt;/h2&gt;
&lt;div&gt;
Setting up a podcast feed is pretty simple IF you have the right tools and services in place. With these first few steps you're now well on your way to being a podcaster.&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/05/podcasting-101-what-are-things-i-need.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s72-c/podcasting.jpeg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6741939616184644425</guid><pubDate>Thu, 16 May 2013 14:39:00 +0000</pubDate><atom:updated>2013-05-16T10:40:13.301-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">podcasting</category><title>Podcasting 101: How To Do A Podcast For Little To No Money</title><description>My two podcasts (&lt;a href="http://blog.alittledead.com/" target="_blank"&gt;A Little Dead Podcas&lt;/a&gt;t and &lt;a href="http://www.thezombiemob.com/" target="_blank"&gt;The Zombie Mob&lt;/a&gt;) recently joined a network of other podcasters called &lt;a href="http://76streetnetwork.com/" target="_blank"&gt;The 76th Street Network&lt;/a&gt;. And after talking with a few other podcasts, I found that not everybody is as familiar with the tools and services that are available.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So what I'm going to do is, over time, write up a series of blog entries here for how to take advantage of those free services and tools and also the little tips and tricks that I've developed over the past four years of hosting my own shows.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Keep an eye out here for &lt;strike&gt;episodes&lt;/strike&gt;&amp;nbsp;installments as they're posted.&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s1600/podcasting.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s640/podcasting.jpeg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/05/podcasting-101-how-to-do-podcast-for.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC9dIl4nxlegwKEB6-s2833Sp1NbKuXq74XFZk9-iUHATBSmFnUP5GsdQrdApAOVk2SWYF04IK_iPLSh3lvUfanYuKWZD4_C0hJ50UAOklS6_EQxyif2rheETfAGE9h5-Wf2xnImXRZhs/s72-c/podcasting.jpeg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-6489465533841063751</guid><pubDate>Thu, 09 May 2013 12:45:00 +0000</pubDate><atom:updated>2013-05-09T08:45:07.027-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">convention</category><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Flock To Fedora</title><description>&lt;div class="tr_bq"&gt;
From the &lt;a href="http://flocktofedora.org/" target="_blank"&gt;website&lt;/a&gt;:&lt;/div&gt;
&lt;blockquote&gt;
For eight years, Fedora users and developers have gathered at an event named for them, the Fedora Users and Developers conference (FUDCon). But we’ve grown, and it’s time for a new approach: Flock.&lt;/blockquote&gt;
&lt;blockquote&gt;
Flock is a brand new conference where Fedora contributors can come together, discuss new ideas, work to make those ideas a reality, and continue to promote the core values of the Fedora community: Freedom, Friends, Features, and First.&lt;/blockquote&gt;
&lt;blockquote&gt;
Fedora and the people who participate in the project encompass so much more than just an interest in Linux. Flock is where you meet with other members of the Fedora community who share whatever your interest is, whether that’s the kernel or the cloud, hardware or UX design. We also want to embrace and invite the growing open hardware community so that we can learn from one another and create better things together.&lt;/blockquote&gt;
The first flock will be held 09-12 August in Charleston, SC. For more, click on the link above. And if you want to present at the conference, please go &lt;a href="http://flocktofedora.org/submit-a-talk/" target="_blank"&gt;here&lt;/a&gt; and submit your topic.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrSOFBreaoi5Pos0r4SxuxyQQFlitaU7DFlBx5rv56kw22xtWQgWiE3pqvWJvBAtHq_ZJhsE0r-0cgCxfbKZRC1RLFMKElILQpTFIjg13WSdfOjBZNnWlP1OJGJiBO9VdidBPEdJEu3tk/s1600/340x_fedora_logo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrSOFBreaoi5Pos0r4SxuxyQQFlitaU7DFlBx5rv56kw22xtWQgWiE3pqvWJvBAtHq_ZJhsE0r-0cgCxfbKZRC1RLFMKElILQpTFIjg13WSdfOjBZNnWlP1OJGJiBO9VdidBPEdJEu3tk/s320/340x_fedora_logo.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
</description><link>http://mcpierce.blogspot.com/2013/05/flock-to-fedora.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrSOFBreaoi5Pos0r4SxuxyQQFlitaU7DFlBx5rv56kw22xtWQgWiE3pqvWJvBAtHq_ZJhsE0r-0cgCxfbKZRC1RLFMKElILQpTFIjg13WSdfOjBZNnWlP1OJGJiBO9VdidBPEdJEu3tk/s72-c/340x_fedora_logo.jpg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-1466735897737261324</guid><pubDate>Thu, 02 May 2013 17:08:00 +0000</pubDate><atom:updated>2013-05-02T13:08:51.303-04:00</atom:updated><title>Close Windows, Open Doors</title><description>&lt;blockquote&gt;
Microsoft wants to keep you locked in to Windows so that it can take your money, your personal data, and your user freedom. They don't want you to know that you have a choice of better operating systems; operating systems that respect your freedom. There are tons of free "as in freedom" software operating systems that you can download and install at no cost. And when they're improved, you can choose whether or not you want to upgrade, without a corporation breathing down your neck.&lt;/blockquote&gt;
&lt;blockquote&gt;
It is time to upgrade your computer, but not to Windows 8. &lt;a href="http://www.fsf.org/windows8/pledge"&gt;Pledge to free your computer today!&lt;/a&gt;&lt;/blockquote&gt;
&lt;center&gt;
&lt;a href="http://www.upgradefromwindows8.com/"&gt;&lt;img alt="Close Windows, Open Doors" src="//static.fsf.org/fsforg/graphics/windows-infographic_share.png" /&gt;&lt;/a&gt;&lt;/center&gt;
</description><link>http://mcpierce.blogspot.com/2013/05/close-windows-open-doors.html</link><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2161762455502736718.post-9044229926071469530</guid><pubDate>Tue, 23 Apr 2013 13:38:00 +0000</pubDate><atom:updated>2013-04-23T09:38:23.222-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">fedora</category><category domain="http://www.blogger.com/atom/ns#">hardware</category><category domain="http://www.blogger.com/atom/ns#">linux</category><title>Fedora 19: Nouveau Test Day Is The 24th</title><description>&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4F9-bqGj78PVmOeECgy9WJJv5WtLNtX-QvCkqV_rl5xta43l90RH8g2B5t5Q6aCgfVjxutbk5W6vMJGdNr8Fy1Cw_6-SOIFkFV_wGM-TP08b3x6J7tHKBD2KEDkMDDj7rBx0tiTT_gXE/s1600/fedora-linux-logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4F9-bqGj78PVmOeECgy9WJJv5WtLNtX-QvCkqV_rl5xta43l90RH8g2B5t5Q6aCgfVjxutbk5W6vMJGdNr8Fy1Cw_6-SOIFkFV_wGM-TP08b3x6J7tHKBD2KEDkMDDj7rBx0tiTT_gXE/s200/fedora-linux-logo.jpg" width="200" /&gt;&lt;/a&gt;Having just received a new laptop at work (Lenovo Thinkpad T53), I was eager to load it with Fedora and get to work. But, unfortunately, there's &lt;a href="http://bugzilla.redhat.com/show_bug.cgi?id=858503" target="_blank"&gt;a known bug&lt;/a&gt; with the nVidia graphics hardware and the nouveau drivers. If I suspend/resume my laptop, the display most likely comes back as unusable. Not locked up (I can still drop to a tty and do "init 3; init 5; exit" to get to workable desktop.&lt;br /&gt;
&lt;br /&gt;
Definitely not a Good Thing™ since I like to have the laptop suspend when I close the lid to change locations, etc. I don't want to go through the whole shutdown and then startup process each time.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVqEfBUwUnfA2Ba4VZ1WNhfHru1pNtXoFG64QUd816cQy6UdwUYdL6KoDehkI-63xOYs2GS46N56e38vw7Q3CH7-y5zwOqJ6kIzfqkEHN2IBioQjecg2aKnRGRWuIW_7-ObOwb1scPSJI/s1600/nvidia-2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="148" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVqEfBUwUnfA2Ba4VZ1WNhfHru1pNtXoFG64QUd816cQy6UdwUYdL6KoDehkI-63xOYs2GS46N56e38vw7Q3CH7-y5zwOqJ6kIzfqkEHN2IBioQjecg2aKnRGRWuIW_7-ObOwb1scPSJI/s200/nvidia-2.jpg" width="200" /&gt;&lt;/a&gt;Fortunately, tomorrow is the Fedora 19 Test Day for &lt;a href="http://fedoraproject.org/wiki/Test_Day:2013-04-24_Nouveau" target="_blank"&gt;Nouveau&lt;/a&gt; and nVidia graphics hardware! So I downloaded the latest F19 x86_64 LiveCD image, put it on a thumbdrive, and will be doing some testing later today and reporting back my findings.&lt;br /&gt;
&lt;br /&gt;
Not the least of which is this one bug that's got me partially missing my old laptop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://mcpierce.blogspot.com/2013/04/fedora-19-nouveau-test-day-is-24th.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4F9-bqGj78PVmOeECgy9WJJv5WtLNtX-QvCkqV_rl5xta43l90RH8g2B5t5Q6aCgfVjxutbk5W6vMJGdNr8Fy1Cw_6-SOIFkFV_wGM-TP08b3x6J7tHKBD2KEDkMDDj7rBx0tiTT_gXE/s72-c/fedora-linux-logo.jpg" width="72"/><thr:total>0</thr:total><author>noreply@blogger.com (Darryl L. Pierce)</author></item></channel></rss>