Live Coding with Rust - Building a Git Command Line Tool

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
sorry about that guys apparently I had myself muted and I didn't even realize it well alright that's fine it's not a big deal I didn't really talk about too much I just kind of went over the general structure of github or not github but get rather and how it indexes files in the backend but we can kind of go over that again so for the benefit of any of you guys who've never been here before and the benefit of the people who are probably watching on YouTube later down the line my name is tensor and we're going to be building a sort of get command line tool and rust and I'm thinking that we're probably going to only be able to implement maybe two or three different commands there are a lot of different commands and to get CLI and yeah it would if we really wanted to implement all them we would be here all day essentially it'd be very it'd be a very long live stream to say the least now this may be something that we want to do at some other point in the future but I'm not really sure well we'll find out based on this live stream whether or not you guys are interested in seeing more so you guys all hear me right correct I'm just making sure I've got the chat here no one's talked since I unmuted myself so I'm just kind of a little curious if you can hear me or not okay I got a yes from not a robot and from Chester thank you guys I appreciate that I'm sorry about all the technical snafus that tend to happen in my livestream I tried something different today and apparently it bit me in the ass anyway I probably shouldn't use curse words on this whatever I think we're all adults here alright so before we get into this I just want to show you guys the folder structure of a normal git project I'm going to open up the get the dot git folder for this project a by default visual studio code just I think it hides it in the in the little directory here so we can just go directly into it and take a look now the files that we want to worry about are this index file and this heads file the index file you can see here it's encrypted and so we can't actually view the data inside of it's mainly just bytes and stuff the heads file is essentially just a reference to where the current head of the repository is and I'll I'll kind of explain that as we're going and a little bit more detail just know that this does exist and then we've got two pieces of metadata we have the config which is like two config for the actual repository and then we have this description which will be a description for the project that's inside of the repository we're not going to worry about these two files with our implementation we're also not going to be worrying about this commit edit message file either this is essentially just when you make a commit on get you can add a message optionally you don't have to but you can and this is where those messages go then we've got all these other folders here we've got hooks info logs objects and reps the ones that were worried about are the objects folder and the rest folder and even inside of the refs folder we're not going to have a remotes for Lou because we're not going to be connecting to a remote repository like this one is and we're not going to have a tags folder and mainly we're just doing this to simplify things maybe in the future we'll add some kind of remote functionality but for now you know because we're probably just going to be implementing in it adding commits there's really no reason to have some kind of remote repository now inside of the heads folder we've got a master file and it's got this hash in it the hash is essentially just the reference of where we are in the repository currently then if you look here it's also the same hash so you can see here that the local repository and the remote repository have the same hash therefore they should be completely synced together then inside of objects here we've got a bunch of different files you can see they're all kind of encoded in a strange way this is what's called libs II encoding we're not going to implement that in our project but yeah so when you actually look at these files you'll find hashes and you'll find the actual source code for our rust files if we're going to commit those or whatever project we're working on yeah and all these files have various different reasons to be here there are pieces of the project pieces of different adds and commits and I'll talk more about that when we actually get into building that functionality enough for now so let's go back into the project that's all so let's just start to build this thing apparently not a robot is seven well I'm sorry about that I'll try not to curse anymore I know you're joking by the way but you know who knows maybe you are actually seven that'd be cool seven-year-old learning the program you'd be a pretty intelligent guy when you grow up all right very least you'd be good with computers probably not good with Caen with people though all right so oh yes right I almost forgot we do have some dependencies we're bringing in here so we're making a command-line tool so we want the Clapp dependency crap to parse command-line arguments and different commands we're gonna bring in rust crypto because we need sha-1 and that's how we make the hashes that you saw before so just need some hashing algorithms and this is a good library for that we're bringing in this reg X library reg X is just of course pretty self-explanatory just regular expressions we're going to use them to search out different parts of our directory and then lazy static lazy static is pretty cool with it allows us to define static variables and have them be lazy in the runtime so lazy and that they don't get evaluated until they have to be so this is mainly important for large things like trees and vectors and large collections of data where you don't necessarily need all the data at once and yeah I highly recommend you guys take a look at lazy static if you work with rust at all all right so here we go with that and actually guys I hate to do this but I'm getting a phone call that I have to take give me about 30 seconds to a minute and I'll be right back you you you you alright guys sorry about that had a colleague was curious about something had to make sure everything was alright okay let's get into this before we really start to implement anything let's build out some errors because we're going to need some errors to report back to us if anything goes wrong so I'll create a module here called errors or error RS let's add it as a sub module and inside of error let's create a Inu and we'll call it to get error because that's the name of our program is to get as intense or get that really it doesn't matter what the name is and then what we're going to be looking for our IO errors and this will have the standard IO error type inside of it we're also going to be looking for errors where we can't find the directory so no directory we're also going to be looking for an invalid commit error and then a invalid index error the IO errors are obviously just errors that we get back from running standard well standard file stuff so if we want to manipulate our directory make files open files read files all that stuff we could potentially get back IO errors and we want to handle those so we want to put them inside of here and then the rest of our errors will be these other arrows here and yeah and if these happen we can do various things with them so we can just throw back a standard error piece and then we don't have to write unwrap after every single line that may potentially cause one of these errors all right so let me actually make this easier by importing some of this stuff so let's import standard IO and then I can just call this as IO error instead we're also going to need probably standard F and C and we want to implement the FMT dissuade trade for our errors so that we can actually display the error messages this of course involves implementing the FM teeth method which takes in a reference to self and then the formatter which is just a reference to a mutable FM t format or type and then this returns back a result and in our case just be a result of a union type and then an FM t error maybe I should let's see probably decrease the size of this so you can see this a little better alright so we're just going to match on self and I will implement each of these cases so if we get back a a key gets IO error and we want to take a reference of the stuff that's inside and we'll just Club its e and we'll just say e dot F and T and then we'll pass in our formatter so that it will actually print out to the command line then let's see we're the no directory error let's see we're going to call formatter dot right STR want to say no directory sound and we're really just writing these out to the console the formatter is just a basically going to work on the console this could work on any other thing like if we made like a graphical user interface we could also make it implement with that as well okay let's see we need to implement these other ones so invalid commits and let me get the other one while I'm edit invalid index and for both of these we're also going to use the formatter right string call for the invalid commit we'll just say a commit is invalid or the commit is invalid rather and then for the index we can just say the index is pull-ups all right let's see we also want to implement the from trait with IO error in it for our T get error and for this we're just gonna add a from function or from method rather which takes the part it gives us takes in our error and will give us back a ticket error so we can convert a normal I owe air into a ticket error and we can just use this from trade to do that so we just say T get error IO error and then we just pass in our error here all right so that's pretty self-explanatory I would think hopefully this but it should go away let's see what's here [Music] this is very annoying missing from implementation because I spelt this wrong sorry about that having dyslexia alright well that's pretty self-explanatory you you yeah I'm not going to use get to because I wanted to actually I wanted to actually implement this stuff myself get to would give me a lot of the features that'd work building out here and I feel like it would just be better to build them ourselves but yeah I know it exists it's a very good library if you want to interact with get and version controlling in general all right so we've got our error and with our error we can now go ahead and create the init command for our application so let's go ahead and make an init got RS file you should be good with this I think I don't think we need anything else for in it and it is just setting up so in it all we do with the net is set up our directories and the various files and stuff inside of those directories so in here let me first wire this up and inside of an ED here we just want to well pull in our errors and then we're gonna need and it should be super is it super quick yeah super okay we're going to need standard FS and we're also going to need standard FS file because we're going to be reading and writing to files and I need years standard IO right speaking of writing files and then actually we're not gonna be reading files we're going to be writing files but we need a symbolic file and we need to be able to write to it we need to be able to get the path so we need standard path and I think that should be it for now and for in it we're just going to create a function here called in it takes in nothing pass us back a result results with our T get error inside of it as the error and then a union type as the actual return type and then we can say let BER get our path new and for our application we'll store everything inside of a folder that's just call it T gets for simplicity and then we can go ahead and use FS to call create dir to create another dir and we want to create the directory for the one that we just created here the dot t get file and notice I'm putting the question mark here so if this comes back with an error it will automatically throw back a T get error so this would be an IR where and if the IR air comes back it'll call the from method that we created before and then it will wrap that inside of a t get error and then pass it back to the screen so we also want to create a directory inside of our ticket directory so I will call this dir join this will be our objects directory no tikis and again we'll have a question mark and we'll repeat this for our arrest directory and then for the head directory inside of ref so refs and then dot join and then heads is the name of this directory so now we have the directory structure we need to add the main head file and actually write the initial data into it so let's make this call it immutable head and use our file create to create it and this will be in path dir join and we'll just call the file with a capital head like that and then we just want to say head rights all to actually write a string in here and we're going to write it just like we saw in the actual get implementation just going to be get raps rafts heads master like this and we need to convert this to bytes I think yeah and again where we use our question mark and then we'll pass back and ok with the Union in it and that should and it looks like it works and to test this I could actually come in here and just call it directly so and it's in it like that we can go ahead and run this let me flip over to that screen so should run should compile and run let's see you when we actually get more commands we'll add in the actual command-line interface but for now I just want to run this to see if it works see if it actually builds out the structure that we want and let's see and it looks like it did work let me bring you back over to the editor you can see here we now have this T git file our folder rather with an objects folder inside of it a reps folder inside of it and then inside of that we've got our heads folder and then inside of this head fire we have our string that just says ref refs headmaster perfect works and perks is to say exactly as we expect it to so that's actually the easy part we've got all the folders set up and everything now we need to be able to interact with them in a way that's well like git and of course get uses various different abstractions so let's uh those first two kind of get you guys to sort of understand what we're going to be doing here so let's see we're not going to be doing anything with objects I don't think all right well first let's talk about blobs so blobs are very simple they well okay let's talk about objects so and yet you've got these generic objects and objects have various different types when you've when you commit files back to get you create various different objects and then these objects are stored in what is essentially a key value store and sort of like a tree at the same time so we've got this like tree shape and then inside of it is this sort of I guess key value store where you're hashing the data and then you're using that hashed as sort of the key for the data itself and the tree itself is a work tree and then you've got the actual get directory so these are the two main things that make up a repository when we are talking about git then inside of this tree and inside of this directory we have our objects and one of the main object types the one that we're going to be working with at least is this blob type the blob type is sort of like a non specified type that just can it can really have anything inside of it and that's what makes it very easy to manipulate because you can just kind of like throw a bunch of data inside of a blob and then you can use that blob to serialize and deserialize back and forth from the files that you want to write and stash and so on all right so we need to implement the logic for this type of well first we need to implement the logic for like the tree and then we want to implement the actual blob itself so let me go ahead and create a file here and call this type stat RS Aquarius we want this to be a sub-module set of type so let's make a enum for the tree first so DM just be called tree inside of it we can have blob entry and the blob will have a name which will be a string and then the hash which will also be a string then we'll also have a tree entry where we have a name string and then a hash string and then we want to have the children of this tree which will just recursively call the tree inside of a vector should be about right let's see thinking we should probably implement the index mm-hm sure how I want to go about doing this sorry guys I'm have a bit of a brain for a moment I'm I know what I want to implement but I'm not sure how I want to go about doing it let's see all right well let's set up the blah blah forget it so all of our blobs just be a public hash string and then the data which will be a vector of u8 which will be just our data as bytes essentially and maybe we don't actually want to put all these types in here but no that's that's fine ah then I guess let's define a commit and now we'll do the commits after let's define the index now I think that's how I want to do it yeah all right let's define the index so the index index no don't want to do that in here sorry about that all right so we've got a tree we've got our blobs and we want to implement some methods for the blobs make all this work properly keep getting text messages sorry guys alright so let's create an implementation block for blog and we want to create some data that will allow us to get these blobs from the directory so we're going to need some imports here let me get them I'm going to need standard i/o standard i/o read going to need standard FS file again and we're going to need standard path path buff and I think we'll probably need our crypto stuff so crypto sha-1 is it sha-1 and then I think we need a digest digest like that yeah and okay so this work like that so that's this is our third-party library here this crypto stuff this will allow us to essentially hash everything in the way that we want to so all right so blob will create a function here our method rather called from path and we're taking the path which is just a path buff type which is just the if you look here is essentially just the path essentially with a string inside of in some metadata so the path that we're referencing inside of our directory alright so then this function here is going to return back an i/o result type and inside that will have that blob so we want to create a file first so file open on our path then we can say get the bytes for the file so let's first create a vector for that and then you can say file dot read to end to read the entire file and then we'll put our bytes in here too or we'll put it into our bytes vector then we can take this and call sha Wan nu to create a sha hash and sha inputs our bytes in here so we're going to hash the bytes and then we can pass back a blob inside of okay where the hash is our sha and I think it's result string yeah and then the data is our bytes let's see she'd go away there we go all right so we read from the from our various files in here and then we convert all that data into bytes and then we create our blob object from that it's actually fairly simple if you think about it all righty so now excuse me I think we want to implement the commit structure or now before that we want to implement the index so let's create a new sub module here called index and the index itself the index is sort of like a staging area so when you add data using like get add the data goes into this index and it doesn't get pushed into the repository at least not officially into the repository until you actually type in commit or something like that so the index itself is the staging tree so it's just a tree with a well we'll have a path here which will be a path buffer and I need to import that and then we'll have the hash tree which will be a b-tree map type which is a type inside of rust that we can import with strings in it and standard i/o get that beat remap then the buff free bop reader and we're going to need a rights like that probably need FS file and of course we'll need our puff pass puff there we go so this is what the index looks like and now we can implement stuff for our index so let's first create a method to create a new one so we pass in the root directory which would be our path buff or a path but rather and the results here will be an index with a tea get error and I need to import that so let me go index equals index the path is just the roots directory they join it with our dot T git folder then we're going to join that with the index folder or the index file rather like this and then the hash tree is just a new B tree map check if index path yes right on okay with our index in it if the path already exists we just return it otherwise we want to essentially build the path so well say let file equal bump reader new file open and we're going to open this at our index path with a little error handle a there then we can say for we're iterating through these files so we want to say for a line in line filed lines like this and we're essentially we want to take each of our lines and convert them into our blob type okay yeah and add them to our blog which will just be a huge vector so you say let just call this L n equal line and then we'll say blob which is just a vector slice a string type equals Ln dot split put these at any white space and then we'll collect them and then we want to check to see our blob blank it's not equal to two will return an error and this will be our T gets error invalid index I think that's what we called it that's our error type there and then if it is longer or if it's not equal to rather we can update our index by passing in blob one and then blob zero and update is a method that we need to implement here and then we'll pass back okay with index inside of it like that let's see you guys so I guess understanding this or am I kind of breezing by a lot of explanations you guys have any questions you can obviously ask them so here's what our update function will look like that's in our car index the self then we want to take in the path which is the first blob or rather the second blob and then we want to take in the hash we just want to insert them directly into our hashes index or hashes vector see let's also make a print function so that we can actually see this thing so itself we'll just say for ref - rap path in stuff dashes hitter and println put in our cash and then our path like that John says that he understands us better than other Lang's with that's that's great what I meant is is not the rust itself the what we're actually implementing here I feel like I've kind of muddled the explanation all right we need to also be able to write on our index and this method will taking the index itself and then it'll pass back a IR result with a just a union type inside of it create our file by getting self dot path so we're essentially just getting the file again and then we can iterate through it again and I can actually reuse this code here so I can say breath - that on the duh this seems about right we just don't want the println instead we want a write Ln and for this we need to pass in mutable index because we're writing to that and then we're going to write our path and hash into the index like this and the index is of course the file that we opened and then just pass back our Union type here and then finally we want to be able to clear the index so clear to take immutable self which is the index itself and then I our results since elf hashes and it's hash tree I keep I keep saying hashes should all be hash tree Supt at hash tree equals be treemap new so we just clear it by recreating the tree or creating a new tree and then we can just call it self dot right to execute this function to repopulate the tree zobelle right let me look through this real quick again see that I didn't have any issues what's with this Oh missing a semicolon on call and rather see I don't think there are any errors there might be a few here it should be capitalized looks about right but we'll see you when we run it and I don't think we'll run it for a little while all right so we've got the index we've got the blob type we've got the tree type we've got our init command already set up and we've got our errors now let's we need some way of interfacing with the directories so for both commit and add so let's create sort of like file service command are not command but structure so module here called filed on RS of course that deleted module didn't it hate that I wish they would fix it already let's see yeah I think this should be alright alright so in here we're going to need a few things standard EMV standard FS standard FS file again and I need to use standard i/o use standard i/o read/write use standard path and we're going to need our path pop and then the path again and then we're going to need a few imports from our own stuff so super let's see the types and I need the blob type super errors gets error and I think that should be alright and it's not errors it's just error hmm we may need to create the commit object first but let me just define this structure so we'll call this file service put in our root directory path buff then the T git directory again another path off and then the object directory again another pathway so root directory is the root of the project the tiga directory is just this to get directory and then the object directory is obviously our objects directory here all right so let's implement some stuff for file service want to create a new one and we still want to use our errors to get error let's define root directory which would just be files service I will have a function which we're going to call find root rather a method which we'll call fine method then we'll have our our tickets Diarra and my gun which will be off of the root directory join this with dot tickets and then to have buff and actually you know what we're doing this let me just create this real quick let's make this not public and we'll have our this will pass back a path buff and then it also have our ticket color in it and so this is just to get our working environment so we'll just say Utes current de rectory equals and the current dura like that these are question mark because if we have an error we can throw it back can we want to loop around do we know [Music] for now let's just pass this back inside of okay so I would say okay parents there later we'll add a loop so that we can check to see whether or not we're inside of the tiga directory or not and if we are then we can address that so now we can actually get the root directory and then that will inform the rest of this so direct directory again we're going to call to our root directory and actually in this case we can just call to t get directory will join this with objects then again we'll call to path tuft then we'll pass back and okay with file service inside of it and we can just say Rueter t get stir and then object er like that to put all these variables in it you you know actually while I'm thinking about it let's create the function to determine whether or not we're inside of our ticket file so let's just call this is T Gibbs and this is going to need a generic yeah generic PE for path going to pass back and pull in we're gonna need a guard here so where P is a sized R has a sized trait and as ref trait implemented on it and it's wrapping around path so now we can just say path as ref join T Gibbs and we can just check to see if this exists and that will give us back our boolean so now that we have that we can come back up here add our loop to loop around and just say if file service and then we just call is t get pass in our current directory or a reference to current directory and then for if it is let me just return this and then we can just say if current directory pop return error or the error part and then we put in our ticket error and what did we call that thing no directory that's one we want that's the air we'll create for this and then that will crash out well lease it'll give us the air that looks better let's see okay so the main reason why we want this file service is to be able to get the head reference and and then get the hash from the head reference so that we can also write our blobs and then do our commits and stuff so let's create some more functions here call this I get had ref and this will pass back a result with the path buff in it get our head file by calling file open stuffed birds directory join and we're looking for our T gets back slash capital head file and we need to get our reference path at first this will just be a stray new so we take the head file I'm going to read it into that string we just created so mutable rough path all righty then let's see we also want to go ahead and take the ref path and probably need to be meter ball reassign it by splitting off the vi index d I'll show you this part here we're gonna split this off so that we can connect this and actually create a path so like for instance if the pass was like dot dot T gets like this well actually on Windows would be like this then it would be refs head master something like that yeah reps heads master and should be heads like that so if we're gonna put it in like this then it would be reps like this and this would throw back an error because this is not a directory obviously so we need to split off this part of the string before we create the directory so then we can just say okay self dot to get Durer join and we joined that directory with the one that we just created which is the ref path and yeah this actually doesn't need to be mutable what's with this apparently this is never used even though I used it up here whatever must be an error all righty so another function we're going to need is right Bob get our blob type so this will help us create our blobs and you say self writes will have a function our method called the right object and this will just take in the hash and and then the path and then we can just are the hash and then the data and then we can just put that into our blob so just say blob hash and then blob data like that and let's actually go ahead and create this so actually let's add this real quick the data was a picture of you eight I think yeah all right so let's say let rob dir equals self-taught object er join you want to get the cash the first two characters of the hash that's the actual directory of the blob inside of here so as we're adding blobs to our objects folder there they'll be referenced by the first two characters of the hash you saw that in the get folders each of the folders had first two characters of the hash that well they had they were made up of two characters but that was actually what it was it's the first two characters of the hash that references each of the objects so that essentially this is the logic that is being used la dirar we need to make sure it exists or not if it doesn't exist first rather they can call FS creates dir to create it and it doesn't matter if we don't populate it with anything then we can just say blob file name which will just be blob dir let's join this mcs will join this with the rest of the hash so from index to on to the end of the hash so the file will be called you know the directory will be called the hash the first two characters in the hash and then the file itself will be called the rest of the hash then we want to write into the file so let's put in our file name dad's and then Rob F write all passing the data and then pass back okay with the Union in it there we go so that would better write the object let's see so now I'm looking at questions Tom wants ask some questions about flutter I know if you how to launch a localhost and access it through a webview you should be able to just use the new loopback the normal Android loopback which i think is 10 what is it let me look it up real quick you it's 10:02 to so when you're connecting to any kind of localhost so you have like a server on like 8080 he would connect to it like that instead of localhost 8080 that's if you're using a video if you're using like any motion I think it's just 10 0 3.2 instead of 0 2.2 anyway that I think that should help you I used that in the other example the rust example or that was like a chat up where we made the front end in flutter so yeah you can go take a look at that yeah it lets you access the localhost that's on your desktop and then access it from the flutter front end if it's on an emulator if you're on a device I'm not sure how that would work but if you're on the emulator that the command I just showed you should work oh yes if you're on a device then you get your the the actual IP address that you'd find for your computer on the network and then you can connect through that bit of a pain to do but you can you can do it that way if you want to as well you yeah you should be able to get from the app and access the app itself so you're accessing the app from all right so if the app is a server and you're accessing it from Android you can access it through that loop back IP address if you want to access your application through the emulator not sure I think that should be alright there's a whole thing on it let me see let me give you the page you can take a look at it there you go just follow that link and read about it it should help you with whatever questions you have anybody has any other questions they can be off topic too you can go ahead and ask them while we're doing this and I'll be sure to answer them all righty so think we're missing a few things here but for now this seems about right um let's say all right so what do we have when we kind of get back into the headspace I was in you you you you now I think we should be able to create the add command so let's do that so just call this ad RS I think we have enough to do that as the mod and and of course that keep it thing keeps trying it out for the alphabetize all the imports and then ends up destroying some okay so we're going to use standard mV use the file service but if we just call it file right so the super file file service use pipes blog that's capital B use our index type and then we can also use the error of course and these should be super I think they have to be super anyway she gets error like that should be alright alright so this is just one function it's like our init command in that it's just one function we have all the the abstraction that we need so let's just call this add data this would be a vector of you ate or a vector of str rather turn back a results with a union in it and a t get error on the air side and let's see just curious if I can just remove this super keyword No okay that's what I thought all right so instantiate a file service by calling foul service new then we can say let current directory let's just kind the rectory can be current Darer like that we can unwrap it I think we can just use our error handling like that create our new index call the file servers get our root directory that were we that was I think that's what we called it you directory all right so now we want to go and live through our aid our ad data and this will have all the files that we're adding to our our index essentially so let's say let full path equal current directory join then we'll add the file to it so that's the actual file name and we'll say let blob equals blob from path do we have this function yet or this method will path put that in there let me see yeah we have from path all right service we have the right blob function which we can call put in our blob then relative path what we need get our full path call strip prefix and this we can call file service root beer root directory then you can call unwrap like that then index dot updates let's hit path to string unwrap and then we also want to pass in our LOM cash and I think it's blob hash tree actually now it's a blob hash it's the tree hash tree okay you all righty and then this for live you can say index right and then okay let me make sure we have that right function yeah you do have the right method in there I should never go that that actually solves everything I'd said this will actually work this will allow us to add files to the back here so let's see let me call it see if it'll work so add at all and then we want to put the data so let's see have a recall this just need to get the data read it in to us to a vector and see you you know it probably should set up clap and actually that's what I'm going to do let's set up clapping here that way we can have both are in it and our and our add commands working so clap app organ sub command and then we can say let n equal app new call our app T gets then let's add our sub commands the first one will be sub command with name this will be 4 in it so when you type in it as a sub command to running this executable it will then execute some stuff and we can even say initialize there are repo and then add another sub command I like clap because it allows you to kind of change it all the chain all the commands together like this so state your sub command and you can even use you can see here it says from yam oh so you can use a yellow file to define all of your commands if you want to I'm just using strings because it's easier this way so we'll also have the add command that's and then add also has an about add a file and then we can also have the argument for add which is just this archetype here so rather than a sub command this is an Arg so our gwit name the Arg will just be called file and then we could add a help to it let me make this readable I'll help just gonna if we do call help it'll just say file to add and then let's see the index of this argument will be one and then we can have multiple of them so this will allow us to add multiple files and then we can also have them be required true like that let's see with uh sorry format in a way that actually looks nice you just do it myself gotta say I wish they would speed up the RLS server it's a kind of pain in the butt that it's so slow and that sometimes the formatter doesn't kick in until the worst opportune times are the least opportune times all right and actually let's bring this down and push these over that looks better we're not done here though actually we are done here we don't need to add the commits sub-command yet because we don't have it so now we can match on M sub command and it's just sub command so now we match on each of the sub commands and if we get back in it and we'll get back some we don't care what's inside of it and we can just match on C you and that we have so in it in it like this and if we get back okay you can print out repo and initialized get back error then we just print out already initialized let's see the be closed like that begone all right we're also going to need add and inside this will have a sub match which will be the the actual arguments the filenames that we're passing in and we can match on them so a match on the add all call which is an add so add at all like this then we can just say sub-match dot value [Music] file unwrap collect and I'll give us a vector of all the different files and then we can just say okay don't really care about the return here not going to print anything out or anything like that if you get an error and we want to handle that error so we'll just print that out just I don't even know what that is it's our error and then we just pass in he like that and let's see oh yes we need the final pattern which is just an empty pattern man wreck nice I spell that right yeah see you [Music] you whoops I didn't mean to do that what's the matter what is it looking for you maybe it doesn't want a tuple that's very strange you okay you go look at the clap documentation because it feel like it's changed recently and it's been a little while since I've used it personally this is how I used to use it so let's take a look gotta fire up Mozilla for this can take a look you all right so Chester the difference between super and crate super is when you're calling from a sub-module and then create I mean I don't think there is a difference anymore if there used to be I recommend looking at the 2018 rust module changes so they've really changed a lot of things like you don't have to externally import libraries anymore which is why you never saw me import like clap or anything like that hang on let me bring up the browser here so yeah you never saw me import any of that stuff because didn't really need to so yeah there are a lot of new pieces to it all right so here we go here's an example so matches and matches occurrences of no that's not what I want sub-command matches when I want either you you okay there's like this new macro version which is kind of cool and not that I actually want to use it you let's say alright so this version they've got command of tests just saying if you get some command test then we want to check to see if debug is present and then it's printed out that seems pretty annoying compared to the old way of doing things see if I can find a good example let's see do they have this is not a good example I want something that shows like multiple different command-line arguments let's see where's a github repository you just no I don't wanna to Travis let me just look it up crap you again only one sub-command that's really annoying subcommands so we've got two of them here sub-command name I guess that's what I want now see they're using tuples - that's really confusing all right well arghhhh matches sub-command I guess the then I'm getting back is an app not an ark match that's strange it's because I didn't call them get matches at the end this thing here yeah once I did that it fixed it all right let me come back into the editor you can see here I had to call this and then that fixed everything let's see if I can fix this part now you so let's see value old file unwrapped collect why is it not letting me collect them all shouldn't be coming in as a string let's see all right so argh with file help at multiple required I mean it should be coming in as a slice of string should be able to collect them [Music] exist with the following tree satisfied okay so it's telling me that there's no iterator apparently which is being just kind of silly let's try again let's try it without the reference so submerge and I'll use of oh maybe it's values of as a posted value of if it's that I'm gonna be really kind of angry file unwrap and then collect it's literally an S no okay what's the saying there we go in reserver elements so what about I make it a reference again yeah so it was literally just s that's really annoying that that pisses me off actually significantly all right well whatever you know I mean I guess this happens one of the things I really just like about rust is that the api's are always changing very drastically especially if you're working on the nightly branch and yeah that can be really really significantly annoying job programmer asks if we're implementing a get tool we're implementing it essentially in rust John says I believe super allows children to call up to the file tree yes it allows sub-modules to call other sub modules so by calling super you can call to the top module and then call as though you're at the top module crate I think also does the same thing though I mean that's the thing if I come in here I let's say you're going to add and just place this with crate should still work perfectly fine that's why I'm saying I don't really think there's much of a difference I mean aside from this nonsense all right I've you know the best way to deal with this is just to add spaces then it doesn't try to destructively delete things to organize them by alpha you know alphabet so anyway yeah see I can just call crate like this and I can also call super and it's literally the same thing right now so I don't know why I chose to use super in this case last time I used to create this time I'm using super I it's not very consistent I wish they would make it more consistent hopefully in the future that it will happen okay so let's go over to the command line and take a look at our new add command and I don't even know how long we've been streaming this far have so maybe we have time to put in commits I think we just barely do I didn't really want to go for two hours but I guess we can do that all right so transition over to the command line and I can just run a car girl run and let's just add let's add our main dot RS file and if we wanted to add more files because we're on Windows we don't have a direct batch command so I can't just like write source start RS if you're on Linux you can do this and then they would just take everything inside of the source directory in and call add with it so instead I have to like add each file independently which is really annoying so if I wanted to add all the files to get like this I could do it anyway I'll put three of them in there it looks like you came back without an error so then we transition back you can see here now inside of our objects folder we have these three different folders each of them are named after the first two characters in the hash for the data and if we look inside of them you can see they actually have our files in them because we're not actually encrypting the data like git does instead we're just pushing the data back here but each one is of course has its own hash name and everything and let's see and then also inside of index you can see it actually is saying okay this hash is associated with this file this hash is associated with this file and so on all right I don't want to save any of that all right so let's add commits while we're at it so for commit let's make a new file heads all right commit is going to be a little bit more complicated than add or then in it because it requires its own special type so with commit we're going to need to and we're also going to probably need to modify our file service again so let's create this structure for commit each commit is going to have a hash which will be an option of string it's also going to have a the data which will be an option of vector u 8 type so vector of bytes then the parent so the parent to the commit got to remember all this is in a tree structure so this will be an option of string type and then we'll have these files which is our big old tree which is that B tree map type that we were using with strings inside of it so of course we need to make those imports for this we're going to need our reg ex library which we haven't used this far so let's bring in our B tree map on B tree sabitri map I all right super crypto sha-1 actually I don't do we need to write superb for third-party libraries I don't think so but we're gonna need our shaw stuff we're also gonna need the digest we're gonna need the Reg annex stuff too it's just our egg x type and then we'll need our error and we'll need our index and I think that's it for now all right so let's now implement some implement methods for commits and of course these are either create or super it doesn't matter as you can see it doesn't really matter I'll just make it consistent use super for both so first we need to create a new function a new method rather new is going to take in the parent this is the parent commit so option of a reference to a commit and then it will pass back you commit and we'll say let commits equal commit the hash for this will be none the data will be none the parent and be match parent and we just want to check to see if the parent exists or not obviously when you first initialize your tree you're not going to have any commits so are your repository rather you're not gonna have any commits so just want to check to see if the commit has the hash in it or reference this would have and then the rest of it we don't care about right now so if it does have a committed it and I I'm using parentheses not brackets then we can say some hash to string and pass it back and then if we get back nothing then we want to pass back in on you and then for files we'll make a new beat remap put that in here oops alrighty so let's see that looks about right all right so so now we ever commit we can use a for loop will reference the hash and then the path again and we're iterating through our parent as a flat map you're going to need to use a closure here and the P stands for parent and we'll just say P dot files either and see you I think I probably want to write it like this yeah so like that scuse me alright so a commits files insert hash to string and then path to string and insert is well this should work let's we're just inserting this into our beat remap and then down here that's back the commit let's see why this is throwing an error no of course the error goes away because ers is really really slow we're going to need a from string function or method rather so pass in the hash and the input both of them will be slices of strings and then this will pass back a result with a commit and then a key gets error so that we can handle the errors and yeah we should create our new commits using our commit new method that we just created and I will pass in none so that it'll be empty by default and then we'll say commits got cash equals some cash to string like that and then we'll use lazy static to define some static references so static referent parent that's what we'll call it this would be a reg X I'll create our new reg X and we can use the string literal reg X Type four rest here so current and the reg X itself is just 0 to 9 a to F and then I think these are size 40 that's what the sha strings are all right so we're looking specifically for anything that matches this pattern and I think we need a space here and then I will have a static rep for a blob which again is another reg X that's really annoying that it won't give me double quotes like that anyway same deal here 0 to 9 a to f ok this is annoying right there we go half like that and of course 40 characters and for this one though we're also looking for a dot at the end like that wrap that let's see you zoom out a little bit so you guys can actually see this all right so apparently lazy statics not in the scope I guess I have to go specifically import the crate and that's very hot I shouldn't have to do that and add the macro you swag and actually I'm gonna go ahead and take this put it inside of Maine I shouldn't have to do this at all apparently I do so we have our two ragged X patterns good good now we want to go four through each of the lines in the input files so are the input strings rather will grab the captures using our parent I can't spell capture that should be captures passing the line and we'll say commit parents equals some caps that get one unwrapped as this tiara to string like that instead of a convoluted line of code but whatever we're matching for the parent and then we also need to match for the caps of the blob so for the cap of the blob we get the first capture for the hash on the first capture will be the hash rather then the path is the second capture then commits files insert past you string and then path to string like that and then we can just go ahead and pass back okay with commit inside of it like that now why are we getting errors here okay errors are gone oh no no all right all right so we're good to go there instead of rushing here it doesn't seem like any of you guys have questions but I'm sure you do have questions because I'm sure this is extremely confusing but whatever I'm gonna write the code now and then I'll go back through it in and kind of explain it after I'm done all right so next we're going to need a print function so that we can print all this out print out the commit itself so if if let some r.fp equal self parent then tell them Tara P and then let's go for breath - left path and stuff that file side hitter hitter right through our files and then we can print out the blobs in here Bob like that put in the hash and then the path okay that's good for plant now we need to update a commit because commits are immutable we need to be able to update them so create a new vector this is gonna get sloppy guys I'm sorry about that because I kind of wanted to get this done but we didn't really get as far as I would have liked I didn't really expect it to be this long actually that's why whatever you don't real quick did you did you do you're gonna need another writeline scribe this God that formatting sucks this is for the broad part Travis need the hash and path okay then after we iterate through he parents and then the blobs and go ahead and create a new sha push in the data to hash it then stuff that hash equals some sha results result string and then stuff data equals some data alright that looks right to me but who knows I probably made multiple errors all right so now let's actually make the commit command so all this is just in service of making commit work okay let me go back through this real quick make sure I'm not going crazy all right so what's going on here mmm type not found in the scope thought I had imported it I guess it got deleted probably actually I can guarantee you got deleted they really need to fix that is the most annoying thing in the world to have your imports just randomly delete themselves [Music] all right so let's create the in and actually before we create the commit you need to go back into the file file and import our in implement a few more functions in here so and actually that's a import super commits commits that's the most annoying thing in the world I knew it was going to happen all right so let's see what do we need I think we're going to need a write object are a read object rather not a write object let's see we've got something to get the head something to write the blob we need something to read the commit and write the commit and we'll need something to read the object so these are actually fairly straightforward read commits it's just taking in self and the hash and outputting a result of commit to get error cause commits from the string - soft ivory object - question mark see I'm strange should return and commit and it to get error so this should be alright now all right we don't have read object implemented yet kind of thought we did because figured we'd well okay so we need to implement that now so read object is like the reverse of our write object function so taking the self take in the hash which is again a slice of string best back an IR result with string in it let mutable data equals string new get a new string so that we can read it from the files and then we need to use our random our file store you get the directories so object names in schools object dirt join again remember the cats in here all the hashes so hash double dot to the file name and then our is the directory rather then we need to get the file name so hash doubled our 2 double dot in this case so directory is two characters first few characters of the hash and then the file name is the last two characters of the hash then they say object file equals file open we're gonna open this object file name then object I'll read two strings what we're going to need we're going to read this into our data as a mutable value immutable reference rather then pass back the data okay so that that worked now will that's implement right commit so we did recommit now right commit it's a right commit to take in self the commits which would be a mutable commit because it's are mutable I our results and this is passing back that the Union type again and then commits that update but we'll call did we even implement that yet I think we did yeah update so we call commit update to update the commit and we want to match on commit and mutable omit at some ref - so if we get a commit where we have some hash and some data and we want that stuff and will specifically call rights objects with the cash and the data in it then we'll call will get the head the stuffed I get head ref is what we want to call for that then we can say let add file equal file create Jesus getting dark in here one sec guys and then head file right all and we're gonna write our hash as bytes into the file and then for the other case just going to be a panic and yet the cash do we need a comma there now why is this thrown errors we'll find out anyway aspect okay see what's going on here how the arizuka of course they are the best air is not gone all right should be as bites not as fight you all right I think that's it so now we can actually implement the commit command yay so let's do that finally alright so commit it's just going to use all the logic that we just created to commit stuff to our repository rather than just adding them so things need to be added first and then they can be committed let's call this commit and this function is going to return a result with potentially an error in it and a union type is the main one so and that's not sure if I imported what we need now we do have error in here we do need our file service we're gonna we have our index and all right so that's I think that's all we're going to need so down here my sister on air whatever did I type it in is T grit of course it in t gets all right create our file service and get the head reference then we're going to say parent - the coolest file service get cash from ref address let me double index equals index nu F s tau root dir we did implement this team we you called it a few times that's what we need get head Ref you I see complaining found stroke path buff but we need a path path okay Oh calling the wrong thing ma'am that's right get headrests did we forget to write the other one don't tell me we forgot to write to get the hash from the ref we did okay it's not too bad so all right I'll just here we need to be able to get the hash as well so given the rough path that is we return an option like string like this and we can match on open Chris Capitol file open with our ref path in here get back and okay refuge F lets you Ashley coolest ring new and after read to string s in our readable hash and wrap this and then pass back some hash for the error don't care let's just pass back none that's all it is it's pretty basic just a pattern match to unwrap all this stuff put in a new string alright so I waited what did I even call that get hash from ref okay there we go why with this i derail myself all right so we've got the index we got the parent hash we've got the head ref we're going to need to now I'll create the parent so let me take the parent hash match on it get some some wrap back let me take that and we just want to say read Nets H H is the head of chorus of the parent then if we get back none and we'll pass back none then we can say I let readable commit equal commands new parent as ref and parents dot map pee-peed print so I print out all the parents then commit add index passing our index camed dot print print thick net right commit I think it sticks in the mutable commits and then index here and then okay I think that's it let's see let's see if they concur we may not have had created this ad from index to our commit type which means we may have to go create that now okay that's strange I could have sworn we did guess not okay well that's not a huge deal it's just a very thin wrapper [Music] so function ad from index immutable self index takes a neat index reference let me say for Raph - Raph and index dot hashes hash in our index isn't it like ash tree best tree so dot files dot insert path to stream and then path dot hew all right I think we're done finally so now it's just a matter of wiring the rest of this up to the command line interface which we've already really set up so it's just a matter of adding the command which is pretty simple actually and then we've got three working git commands there's actually something considering it's only taking us about an hour and eight minutes let's finish that and then I'll take whatever questions you guys have hopefully I've explained this well enough I'm not sure I have though I sell before I do that let's add the commands here so like we did with our other sub commands just a matter of chaining everything together so sub command again and sub and with name omits and this doesn't have a party mints it's just a sub command so that's a change just what we'll just say and that's really it and we don't need to do anything else with it then down here we're looking for commits and then I think it's just some we even need the some no some don't care what's in it match on music this let's call her commit command then get back and okay with a union we went to pass back that Union and if you get an error in it then we'll print out that error and there we go finally you unwrapped is for when you want to unwrap a data type that is wrapped around something sort of like for instance an option type you can either have some value or you can have none and nothing there's nothing inside of num if you want to unwrap from an option type then you call the unwrap method on it and it allows you to automatically unwrap the inner value the issue with calling unwrap there was that you you're not actually dealing with any kind of errors or panics instead you're just saying alright well I'm going to assume that this will be some value and it'll be the right value and so usually when you're working in production you won't actually call unwrap at all and in fact in a lot of the application you'll see that I have these question marks the question marks deal with the result type which again is like the option type in that it can either have an OK value with some data inside of it or an error value with some data inside of it and with these question marks we're basically saying all right unwrap it accept unwrap it with the logic of our t get error type that we set up in the very beginning of our application so all of the calls that have the question marks here they will handle the errors using the t get error handling that we set up but if we call unwrap then we have nothing to handle the error so like here we're calling in rep that's simply because well I don't even know why I'm calling unwrap here I should probably put a question mark but I don't know I'm going to get into that ready let's get back into our command line and run this thing see if we can commit some stuff so in this case with ADD we just added the files each individually with command we can just call commit let's see we get the system cannot find the path specified so there is some kind of error in here that I'm going to have to look for now let's see did we actually get a commit object to happen no we didn't all right so let me go through commit real quick fortunately I don't have much time all right we make our new file service head riff dadadada it could be an error here or we call her the root directory it should be fine though recommit Todd uh you actually actually we could just see like I could just call print alone put in a debug flag here and just call F has root directory and see what that is and according to this I didn't even print out so I'm thinking that the error is coming from our regular expressions so let me take a look at those real quick potentially from our regular expressions could be something else let me think I mean these look fine to me um there's something about them that the format looks alright the second one I'm missing a parenthesis there and I'm even missing a parenthesis for the first one - that's not good you well we're still getting the same error but at least we fixed the regular expressions if this error is happening on Oh you know what I know I know exactly what it is all right you see here we didn't have the dot they're missing the dot I think that's it I think that's exactly the problem all right let's give this another shot let me clear this out try calling it there we go perfect so these are our commits you can see we're committing three blobs the hashes are here and then the files are here if we go back to the to this let's see we now I think we should have a new object here's the new object with the commit in it also this new master in the refs file this is the actual commit which has now changed the the actual head that were at so this is the new hash that were synced to inside of our repository so now if I go back into the command line and add some more files let's say let's add the file dot RS and what didn't we add I don't know let's add I like commit because we did a lot of work on that all right and now let's commit them again and now we've got a parent you can see here that was the old hash that we were just on and now we're creating a new tree with these five blobs and that ship now gave us a new hash that we're on so let's jump back over and let's close all this see all right so that's a new hash we've got a bunch more directories in here let's see where is the here's the actual commit you can see here's the parent our index should be updating that's something that I need to look into because that's definitely an error index should be updating with a hash as well but apparently it's not so that's something I definitely need to debug but the rest of it seems to be working as intended if we wanted to continue with this it would be a matter of adding the Z Lib encryption then adding more commands like the ability to check out the data after we put it back or check out new branches and stuff pull data push data add remote repositories do cat on the files and stuff like that alright guys well I'm gonna close out the stream now do you have any questions or comments or any anything in general to any any particular questions comments concerns feedback standing of it you and let me well I'm doing this one waiting for you guys to answer it let me I'm gonna actually add this to the get ignore and then now well I'll just commit all this stuff ironically I'm using it inside of a good tool yeah or to the repository you guys can take a look at it if you want to that's a fair answers keep up the good work thank you and he enjoyed it quite a lot I appreciate that sorry it was a little confusing I'm sure but uh I think at the very end we got into a nice stride which is good it looks like everything was committed so I'm going to be streaming tomorrow I still haven't decided what I want to do probably be around the same time frame in fairness to the other subscribers I think I'll probably go back and do some more flutters I'll do some gyal I'm not really sure put up a pearl tonight and see what you guys want to see I'd love to do more rust but sometimes it could be like banging my head against the wall with the compiler John says awesome stream thanks man yeah no thank you and for all of you who are in the stream if you want to support me get more live streams like this you can go check out my patreon you can go check out on my other videos just watching the videos there's enough support in my opinion and I never say this but if you want to you should like those videos and comment on them and do stuff like that even if you dislike the videos dislike them too helps the algorithm spread my videos around and then more people see them and that helps rust seems a bit more involved than go in some respects it certainly is it's got more of a functional paradigm than go um one of the things I hear a lot about NGO is that Google will deliberately designed it so that it's fairly simple and so as a result it's pretty easy to replace people who do go honestly I don't agree with that I think it's pretty callous to say that actually go is a interesting language in its own right certainly very can be very involved especially when you you start to work with the concurrency primitives and stuff as far as Russ goes it's just there are two different two different domains in my opinion they both may be considered quote unquote systems a lot of programming languages but the reality is that they're not really Russ is more like C++ whereas go is more for like net and for like web based servers and stuff like that yeah it goes great for web stuff then it's good for things like docker like small self-contained small self-contained systems are perfect for go Russ is good at that too but it's good in a different way it's got its own little niche in there too alright guys my son's like my voice is killing me and I should get something to eat so thanks for coming to the stream if you want to check out tomorrow stream like I said I'll have a pull up you could vote on what you want to see and and yeah see some of you tomorrow and I'll see you some of you guys later you you you and it looks like that's it all right guys talk to you later you you
Info
Channel: Tensor Programming
Views: 7,345
Rating: 4.9613528 out of 5
Keywords: rustlang, programming in rust, rustlang tutorial, rust tutorial, programming, programming tutorial, learn to code, learn to program, coding, learning rustlang, rustlang project, learn rust, learn rustlang, rust programming, learn rust lang, rust language, rust lang, rust lang tutorial, rust git, rust command line, rust cli, rust lang 2019, version control, software engineering, web development
Id: mVuq8IkfkiY
Channel Id: undefined
Length: 137min 5sec (8225 seconds)
Published: Thu May 16 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.